The R+Python Combination May Be the Best Way to Analyze SCENIC

1. Introduction

When using SCENIC for transcription factor co-expression network prediction, there is a particularly troublesome step involving runGenie3, which infers gene regulatory networks (GRN) based on the random forest algorithm. The output includes a matrix of TF-gene pairs and their regulatory strengths. This step not only consumes a lot of memory but also does not support parallel computation in R. Typically, the computation time for 10,000 cells can exceed a week, and it often crashes halfway through, which clearly does not meet the daily production needs. However, in Python, grnboost2 can utilize distributed parallel computing, significantly shortening this process: it is dozens of times faster than the R version. The downside is that PySCENIC omits many intermediate outputs and visualizations from SCENIC, which is obviously unacceptable. In the tutorial of the SCENIC single-cell transcription factor prediction manual, we also mentioned acceleration methods: you can directly call the Python library arboreto.algo in R using the reticulate package to complete the computation process of grnboost2. Of course, if you find it too difficult to learn, don’t hesitate to reach out to us for assistance~ Contact customer service via WeChat [Biomamba_yunying] to leave your request.

# Gene co-expression network calculation
mymethod <-'grnboost2'# 'grnboost2'
library(reticulate)
if(mymethod=='runGenie3'){
runGenie3(exprMat_filtered_log, scenicOptions)
}else{
  arb.algo =import('arboreto.algo')
tf_names =getDbTfs(scenicOptions)
tf_names = Seurat::CaseMatch(
search = tf_names,
match =rownames(exprMat_filtered))
  adj = arb.algo$grnboost2(
as.data.frame(t(as.matrix(exprMat_filtered))),
tf_names=tf_names, seed=2025L
  )
colnames(adj) =c('TF','Target','weight')
saveRDS(adj,file=getIntName(scenicOptions,
'genie3ll'))
}

The problem is that the above R code block often encounters loading failures for arboreto, either not found:

The R+Python Combination May Be the Best Way to Analyze SCENIC

or dependency issues.

reticulate::use_python('/home/biomamba/.local/share/r-miniconda/envs/r-reticulate/bin/python') >   arb.algo = import('arboreto.algo') Error in py_module_import(module, convert = convert) :    ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /home/biomamba/.local/share/r-miniconda/envs/r-reticulate/lib/python3.8/site-packages/pandas/_libs/window/aggregations.cpython-38-x86_64-linux-gnu.so) Run `reticulate::py_last_error()` for details.

Or there are compatibility issues between R and Python data:

The R+Python Combination May Be the Best Way to Analyze SCENIC

Therefore, the safest approach is to let R and Python work independently, that is, generate exprMat_filtered and export it locally, and complete the analysis in pure Python. The visualization highlights are as follows:

The R+Python Combination May Be the Best Way to Analyze SCENIC

2. The R+Python Combination

If you have difficulty understanding the following content, you may want to study the:SCENIC single-cell transcription factor learning manual

This tutorial is demonstrated in a Linux environment using Rstudio. Those with insufficient computing resources can refer to:Environment for bioinformatics that supports your graduate studiesDedicated server, no need to seek help for bioinformatics analysis5090 is finally availableVisit link:https://biomamba.xiyoucloud.net/Welcome to contact customer service via WeChat [Biomamba_yunying] for assistance

1. Load R Packages

if (!requireNamespace("BiocManager", quietly =TRUE))install.packages("BiocManager")
BiocManager::version()
## [1] '3.20'
# When your Bioconductor version is greater than 4.0
if(!require(SCENIC))BiocManager::install(c("AUCell", "RcisTarget"),ask = F,update = F);BiocManager::install(c("GENIE3"),ask = F,update = F)# These three packages are obviously essential to install
### Optional packages:
# AUCell dependency packages
if(!require(SCENIC))BiocManager::install(c("zoo", "mixtools", "rbokeh"),ask = F,update = F) 
### t-SNEs computation dependency packages:
if(!require(SCENIC))BiocManager::install(c("DT", "NMF", "ComplexHeatmap", "R2HTML", "Rtsne"),ask = F,update = F)

# # These packages are used for parallel computation, unfortunately, they are not supported on Windows, so it is best to switch to Linux for large data calculations:
if(!require(SCENIC))BiocManager::install(c("doMC", "doRNG"),ask = F,update = F)
# Visualization output

# To export/visualize in http://scope.aertslab.org
if (!requireNamespace("devtools", quietly =TRUE))install.packages("devtools")
if(!require(SCopeLoomR))devtools::install_github("aertslab/SCopeLoomR", build_vignettes =TRUE)# SCopeLoomR is used to obtain test data

if (!requireNamespace("arrow", quietly =TRUE)) BiocManager::install('arrow')
# This package must be installed, otherwise an error will occur at runSCENIC_2_createRegulons, indicating that 'dbs' does not exist
library(SCENIC)# This has been installed, let's see if it can load normally

if(!require(SCENIC))devtools::install_github("aertslab/SCENIC") 
packageVersion("SCENIC")# Here I installed version 1.3.1
## [1] '1.3.1'
library(SCENIC)
library(RcisTarget)
library(AUCell)
library(Seurat)

2. Preprocessing in R

# Initialize SCENIC settings
data(list="motifAnnotations_mgi_v9", package="RcisTarget")
motifAnnotations_mgi <- motifAnnotations_mgi_v9
scenicOptions <-initializeScenic(org="mgi",# mouse fill 'mgi', human fill 'hgnc', fly fill 'dmel') 
dbDir="./data/mouse.mm9/", 
nCores=6)# Here you can set parallel computation
## Motif databases selected: 
##   mm9-500bp-upstream-7species.mc9nr.feather 
##   mm9-tss-centered-10kb-7species.mc9nr.feather
## Using the column 'features' as feature index for the ranking database.
## Using the column 'features' as feature index for the ranking database.
library(Seurat)
# Read test object
scRNA <-readRDS('./data/pbmcrenamed.rds')  
# View test object dimensionality reduction plot:
DimPlot(scRNA) 

The R+Python Combination May Be the Best Way to Analyze SCENIC

# Get expression matrix:
exprMat <-GetAssayData(scRNA ,'RNA','count')
# Convert to matrix object:
exprMat <-as.matrix(exprMat)
# Preliminary filtering of genes:
genesKept <-geneFiltering(exprMat, scenicOptions)
## Maximum value in the expression matrix: 26404
## Ratio of detected vs non-detected: 0.12
## Number of counts (in the dataset units) per gene:
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##      0.0      3.0     48.0    407.6    214.0 187278.0
## Number of cells in which each gene is detected:
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    0.00    3.00   39.00   99.42  143.00  897.00
## 
## Number of genes left after applying the following filters (sequential):
##  11369   genes with counts per gene > 27
##  11338   genes detected in more than 9 cells
## Using the column 'features' as feature index for the ranking database.
##  10021   genes available in RcisTarget database
## Gene list saved in int/1.1_genesKept.Rds
exprMat_filtered <- exprMat[genesKept, ]
# Calculate Spearman correlation:  
runCorrelation(exprMat_filtered, scenicOptions)
# Take log:
exprMat_filtered_log <-log2(exprMat_filtered+1) 

# Get TF names:
tf_names =getDbTfs(scenicOptions)
tf_names = Seurat::CaseMatch(
search = tf_names,
match =rownames(exprMat_filtered))

# Export expression matrix (needs to be transposed, as in Python, samples are usually rows and genes are columns) for subsequent Python reading:
write.csv(t(exprMat_filtered), file ="./data/expr_matrix_transposed.csv", row.names =TRUE)

# Export TF name list
write.csv(data.frame(tf_names = tf_names), file ="./data/tf_names.csv", row.names =FALSE)

3. Complete in Python<span>grnboost</span>

### The following commands are executed in Python ###
import pandas as pd
from arboreto.algo import grnboost2

# Read R exported data
expr_matrix = pd.read_csv("data/expr_matrix_transposed.csv", index_col=0)
tf_names = pd.read_csv("data/tf_names.csv")["tf_names"].tolist()

# Ensure TF names exist in the expression matrix genes
available_genes = expr_matrix.columns.tolist()
tf_names = [tf for tf in tf_names if tf in available_genes]

# Run GRNBoost2
adj = grnboost2(
    expr_matrix,
    tf_names=tf_names,
    seed=2023,
    verbose=True
)

# Rename columns to match the expected format in R
adj.columns = ['TF', 'Target', 'weight']

# Save results (in CSV format readable by R)
adj.to_csv("data/grnboost2_results.csv", index=False)

The following is the running prompt information:

>>>### The following commands are executed in Python ###
>>>import pandas as pd
>>>from arboreto.algo import grnboost2
>>>
>>># Read R exported data
>>> expr_matrix = pd.read_csv("data/expr_matrix_transposed.csv", index_col=0)
>>> tf_names = pd.read_csv("data/tf_names.csv")["tf_names"].tolist()
>>>
>>># Ensure TF names exist in the expression matrix genes
>>> available_genes = expr_matrix.columns.tolist()
>>> tf_names = [tf for tf in tf_names if tf in available_genes]

>>>
>>># Run GRNBoost2
>>> adj = grnboost2(
...     expr_matrix,
...     tf_names=tf_names,
...     seed=2023,
...     verbose=True
... )
preparing dask client

parsing input
creating dask graph
19 partitions
computing dask graph
shutting down client and local cluster
finished
>>>
>>># Rename columns to match the expected format in R
>>> adj.columns = ['TF', 'Target', 'weight']
>>>
>>># Save results (in CSV format readable by R)
>>> adj.to_csv("data/grnboost2_results.csv", index=False)

4. Complete the Classic 4 Steps of SCENIC in R

Back to R:

# Read the GRN results output by Python
adj <-read.csv("data/grnboost2_results.csv")
# Convert to data frame and set column names (ensure consistency with previous format)
adj <-as.data.frame(adj)
colnames(adj) <-c('TF', 'Target', 'weight')

# Save as RDS file for subsequent analysis
saveRDS(adj, file =getIntName(scenicOptions, 'genie3ll'))

# Verify results
cat("Successfully read GRNBoost2 results, with a total of", nrow(adj), "regulatory relationships\n")

# Run the classic SCENIC steps 1-4
exprMat_log <-log2(exprMat+1)
scenicOptions@settings$dbs <- scenicOptions@settings$dbs["10kb"] # Toy run settings
scenicOptions <-runSCENIC_1_coexNetwork2modules(scenicOptions)

scenicOptions <-runSCENIC_2_createRegulons(scenicOptions, coexMethod=c("top5perTarget")) # Toy run settings
scenicOptions <-runSCENIC_3_scoreCells(scenicOptions, exprMat_log)

scenicOptions <-runSCENIC_4_aucell_binarize(scenicOptions)# Binarize the AUCell matrix

# Save the image
save.image('data/biomamba_scenic.rdata')
# At this point, we have the same project files as executing SCENIC purely in R:
tree ./int
## [01;34m./int[00m
## ├── 1.1_genesKept.Rds
## ├── 1.2_corrMat.Rds
## ├── 1.4_GENIE3_linkList.Rds
## ├── 1.5_weightPlot.pdf
## ├── 1.6_tfModules_asDF.Rds
## ├── 2.1_tfModules_forMotifEnrichmet.Rds
## ├── 2.2_motifs_AUC.Rds
## ├── 2.3_motifEnrichment.Rds
## ├── 2.4_motifEnrichment_selfMotifs_wGenes.Rds
## ├── 2.5_regulonTargetsInfo.Rds
## ├── 2.6_regulons_asGeneSet.Rds
## ├── 2.6_regulons_asIncidMat.Rds
## ├── 3.1_regulons_forAUCell.Rds
## ├── 3.2_aucellGenesStats.pdf
## ├── 3.3_aucellRankings.Rds
## ├── 3.4_regulonAUC.Rds
## ├── 3.5_AUCellThresholds_Info.tsv
## ├── 3.5_AUCellThresholds.Rds
## ├── 4.1_binaryRegulonActivity.Rds
## ├── 4.2_binaryRegulonActivity_nonDupl.Rds
## ├── 4.3_regulonSelections.Rds
## ├── 4.4_binaryRegulonOrder.Rds
## └── tSNE_AUC_50pcs_30perpl.Rds
## 
## 0 directories, 23 files
# Read AUCell Score matrix:
auc_score <-getAUC(readRDS("int/3.4_regulonAUC.Rds"))
# Add to annotation information:
scRNA <-AddMetaData(scRNA,metadata =t(auc_score))

# Violin plot for a few transcription factors:
VlnPlot(scRNA,rownames(auc_score)[1:10],stack = T,
cols =c(ggsci::pal_aaas()(8),ggsci::pal_bmj()(8))
        )

The R+Python Combination May Be the Best Way to Analyze SCENIC

More visualizations can be seen in:SCENIC single-cell transcription factor learning manualSCENIC single-cell transcription factor downstream explorationSCENIC transcription factor regulatory network diagram

3. Test Files and Demonstration Environment

Any tutorial that does not provide test files and analysis environment versions is untrustworthy. The code and test files provided in this post can be downloaded from the following link:

Files shared via cloud storage: R and Python combined analysis SCENIC process

Link: https://pan.baidu.com/s/1DQdzV7QzuwJ89-Cs7xsnmQ?pwd=tfdx

Extraction code: tfdx

The R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICR language demonstration environment:

sessionInfo()
## R version 4.4.2 (2024-10-31)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 20.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3;  LAPACK version 3.9.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Etc/UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] Seurat_5.2.1       SeuratObject_5.0.2 sp_2.2-0           AUCell_1.28.0     
## [5] RcisTarget_1.26.0  SCopeLoomR_0.13.0  SCENIC_1.3.1      
## 
## loaded via a namespace (and not attached):
##   [1] RcppAnnoy_0.0.22            splines_4.4.2              
##   [3] later_1.4.1                 bitops_1.0-9               
##   [5] tibble_3.2.1                R.oo_1.27.0                
##   [7] polyclip_1.10-7             graph_1.84.1               
##   [9] XML_3.99-0.18               fastDummies_1.7.5          
##  [11] lifecycle_1.0.4             globals_0.16.3             
##  [13] lattice_0.22-6              hdf5r_1.3.12               
##  [15] MASS_7.3-64                 magrittr_2.0.3             
##  [17] plotly_4.10.4               sass_0.4.9                 
##  [19] rmarkdown_2.29              jquerylib_0.1.4            
##  [21] yaml_2.3.10                 remotes_2.5.0              
##  [23] httpuv_1.6.15               sctransform_0.4.1          
##  [25] spam_2.11-1                 spatstat.sparse_3.1-0      
##  [27] sessioninfo_1.2.2           pkgbuild_1.4.6             
##  [29] reticulate_1.43.0.9001      cowplot_1.1.3              
##  [31] pbapply_1.7-2               DBI_1.2.3                  
##  [33] RColorBrewer_1.1-3          abind_1.4-8                
##  [35] pkgload_1.4.0               zlibbioc_1.52.0            
##  [37] Rtsne_0.17                  GenomicRanges_1.58.0       
##  [39] purrr_1.0.2                 R.utils_2.12.3             
##  [41] BiocGenerics_0.52.0         RCurl_1.98-1.16            
##  [43] GenomeInfoDbData_1.2.13     IRanges_2.40.1             
##  [45] S4Vectors_0.44.0            ggrepel_0.9.6              
##  [47] irlba_2.3.5.1               spatstat.utils_3.1-4       
##  [49] listenv_0.9.1               openintro_2.5.0            
##  [51] goftest_1.2-3               airports_0.1.0             
##  [53] RSpectra_0.16-2             spatstat.random_3.4-1      
##  [55] annotate_1.84.0             fitdistrplus_1.2-2         
##  [57] parallelly_1.42.0           DelayedMatrixStats_1.28.1  
##  [59] codetools_0.2-20            DelayedArray_0.32.0        
##  [61] tidyselect_1.2.1            UCSC.utils_1.2.0           
##  [63] farver_2.1.2                spatstat.explore_3.4-3     
##  [65] matrixStats_1.5.0           stats4_4.4.2               
##  [67] jsonlite_1.8.9              ellipsis_0.3.2             
##  [69] progressr_0.15.1            ggridges_0.5.6             
##  [71] survival_3.8-3              tools_4.4.2                
##  [73] ica_1.0-3                   Rcpp_1.0.14                
##  [75] glue_1.8.0                  gridExtra_2.3              
##  [77] SparseArray_1.6.0           xfun_0.50                  
##  [79] MatrixGenerics_1.18.1       usethis_3.1.0              
##  [81] GenomeInfoDb_1.42.1         dplyr_1.1.4                
##  [83] withr_3.0.2                 BiocManager_1.30.25        
##  [85] fastmap_1.2.0               digest_0.6.37              
##  [87] R6_2.5.1                    mime_0.12                  
##  [89] colorspace_2.1-1            scattermore_1.2            
##  [91] tensor_1.5                  spatstat.data_3.1-6        
##  [93] RSQLite_2.3.9               R.methodsS3_1.8.2          
##  [95] ggsci_3.2.0                 tidyr_1.3.1                
##  [97] generics_0.1.3              data.table_1.16.4          
##  [99] usdata_0.3.1                httr_1.4.7                 
## [101] htmlwidgets_1.6.4           S4Arrays_1.6.0             
## [103] uwot_0.2.2                  pkgconfig_2.0.3            
## [105] gtable_0.3.6                blob_1.2.4                 
## [107] lmtest_0.9-40               XVector_0.46.0             
## [109] htmltools_0.5.8.1           profvis_0.4.0              
## [111] dotCall64_1.2               GSEABase_1.64.0            
## [113] scales_1.3.0                Biobase_2.66.0             
## [115] png_0.1-8                   spatstat.univar_3.1-3      
## [117] knitr_1.49                  rstudioapi_0.17.1          
## [119] reshape2_1.4.4              tzdb_0.4.0                 
## [121] nlme_3.1-168                cachem_1.1.0               
## [123] zoo_1.8-12                  stringr_1.5.1              
## [125] KernSmooth_2.23-26          parallel_4.4.2             
## [127] miniUI_0.1.1.1              arrow_18.1.0.1             
## [129] AnnotationDbi_1.68.0        pillar_1.10.1              
## [131] grid_4.4.2                  vctrs_0.6.5                
## [133] RANN_2.6.2                  urlchecker_1.0.1           
## [135] promises_1.3.2              xtable_1.8-4               
## [137] cluster_2.1.8               evaluate_1.0.3             
## [139] readr_2.1.5                 cli_3.6.3                  
## [141] compiler_4.4.2              rlang_1.1.5                
## [143] crayon_1.5.3                future.apply_1.11.3        
## [145] labeling_0.4.3              plyr_1.8.9                 
## [147] fs_1.6.5                    stringi_1.8.4              
## [149] deldir_2.0-4                viridisLite_0.4.2          
## [151] assertthat_0.2.1            munsell_0.5.1              
## [153] Biostrings_2.74.1           lazyeval_0.2.2             
## [155] spatstat.geom_3.4-1         devtools_2.4.5             
## [157] Matrix_1.7-2                RcppHNSW_0.6.0             
## [159] hms_1.1.3                   patchwork_1.3.0            
## [161] sparseMatrixStats_1.18.0    bit64_4.6.0-1              
## [163] future_1.34.0               ggplot2_3.5.1              
## [165] KEGGREST_1.46.0             shiny_1.10.0               
## [167] SummarizedExperiment_1.36.0 ROCR_1.0-11                
## [169] igraph_2.1.4                memoise_2.0.1              
## [171] bslib_0.9.0                 bit_4.5.0.1                
## [173] cherryblossom_0.1.0

Python environment:The R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENIC

How to Contact Us

The R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICLeave a message to receive materials, an out-of-the-box single-cell analysis image via WeChat [Biomamba_yunying], making it convenient for everyone to communicate at any time. We have also built a group chat matrix, and everyone is welcome to join the discussion.After reading these articles, you can add tips for beginners in bioinformatics without searching, you have no right to speak

Students who already have contact information for the bioinformatics basedo not need to add again

The R+Python Combination May Be the Best Way to Analyze SCENICThe R+Python Combination May Be the Best Way to Analyze SCENICEvery like and view you give, I take seriously as appreciation

Leave a Comment