KeTuTu's picture
Upload 46 files
2999286 verified
#!/usr/bin/env python
# coding: utf-8
# # Different Expression Analysis
#
# An important task of bulk rna-seq analysis is the different expression , which we can perform with omicverse. For different expression analysis, ov change the `gene_id` to `gene_name` of matrix first. When our dataset existed the batch effect, we can use the SizeFactors of DEseq2 to normalize it, and use `t-test` of `wilcoxon` to calculate the p-value of genes. Here we demonstrate this pipeline with a matrix from `featureCounts`. The same pipeline would generally be used to analyze any collection of RNA-seq tasks.
#
# Colab_Reproducibility:https://colab.research.google.com/drive/1q5lDfJepbtvNtc1TKz-h4wGUifTZ3i0_?usp=sharing
# In[1]:
import omicverse as ov
import scanpy as sc
import matplotlib.pyplot as plt
ov.plot_set()
# ## Geneset Download
#
# When we need to convert a gene id, we need to prepare a mapping pair file. Here we have pre-processed 6 genome gtf files and generated mapping pairs including `T2T-CHM13`, `GRCh38`, `GRCh37`, `GRCm39`, `danRer7`, and `danRer11`. If you need to convert other id_mapping, you can generate your own mapping using gtf Place the files in the `genesets` directory.
# In[2]:
ov.utils.download_geneid_annotation_pair()
# Note that this dataset has not been processed in any way and is only exported by `featureCounts`, and Sequence alignment was performed from the genome file of CRCm39
#
# sample data can be download from: https://raw.githubusercontent.com/Starlitnightly/omicverse/master/sample/counts.txt
# In[3]:
#data=pd.read_csv('https://raw.githubusercontent.com/Starlitnightly/omicverse/master/sample/counts.txt',index_col=0,sep='\t',header=1)
data=ov.read('data/counts.txt',index_col=0,header=1)
#replace the columns `.bam` to ``
data.columns=[i.split('/')[-1].replace('.bam','') for i in data.columns]
data.head()
# ## ID mapping
#
# We performed the gene_id mapping by the mapping pair file `GRCm39` downloaded before.
# In[4]:
data=ov.bulk.Matrix_ID_mapping(data,'genesets/pair_GRCm39.tsv')
data.head()
# ## Different expression analysis with ov
#
# We can do differential expression analysis very simply by ov, simply by providing an expression matrix. To run DEG, we simply need to:
#
# - Read the raw count by featureCount or any other qualify methods.
# - Create an ov DEseq object.
# In[5]:
dds=ov.bulk.pyDEG(data)
# We notes that the gene_name mapping before exist some duplicates, we will process the duplicate indexes to retain only the highest expressed genes
# In[6]:
dds.drop_duplicates_index()
print('... drop_duplicates_index success')
# We also need to remove the batch effect of the expression matrix, `estimateSizeFactors` of DEseq2 to be used to normalize our matrix
# In[7]:
dds.normalize()
print('... estimateSizeFactors and normalize success')
# Now we can calculate the different expression gene from matrix, we need to input the treatment and control groups
# In[8]:
treatment_groups=['4-3','4-4']
control_groups=['1--1','1--2']
result=dds.deg_analysis(treatment_groups,control_groups,method='ttest')
result.head()
# One important thing is that we do not filter out low expression genes when processing DEGs, and in future versions I will consider building in the corresponding processing.
# In[9]:
print(result.shape)
result=result.loc[result['log2(BaseMean)']>1]
print(result.shape)
# We also need to set the threshold of Foldchange, we prepare a method named `foldchange_set` to finish. This function automatically calculates the appropriate threshold based on the log2FC distribution, but you can also enter it manually.
# In[10]:
# -1 means automatically calculates
dds.foldchange_set(fc_threshold=-1,
pval_threshold=0.05,
logp_max=6)
# ## Visualize the DEG result and specific genes
#
# To visualize the DEG result, we use `plot_volcano` to do it. This fuction can visualize the gene interested or high different expression genes. There are some parameters you need to input:
#
# - title: The title of volcano
# - figsize: The size of figure
# - plot_genes: The genes you interested
# - plot_genes_num: If you don't have interested genes, you can auto plot it.
# In[11]:
dds.plot_volcano(title='DEG Analysis',figsize=(4,4),
plot_genes_num=8,plot_genes_fontsize=12,)
# To visualize the specific genes, we only need to use the `dds.plot_boxplot` function to finish it.
# In[12]:
dds.plot_boxplot(genes=['Ckap2','Lef1'],treatment_groups=treatment_groups,
control_groups=control_groups,figsize=(2,3),fontsize=12,
legend_bbox=(2,0.55))
# In[13]:
dds.plot_boxplot(genes=['Ckap2'],treatment_groups=treatment_groups,
control_groups=control_groups,figsize=(2,3),fontsize=12,
legend_bbox=(2,0.55))
# ## Pathway enrichment analysis by ov
#
# Here we use the `gseapy` package, which included the GSEA analysis and Enrichment. We have optimised the output of the package and given some better looking graph drawing functions
#
# Similarly, we need to download the pathway/genesets first. Five genesets we prepare previously, you can use `ov.utils.download_pathway_database()` to download automatically. Besides, you can download the pathway you interested from enrichr: https://maayanlab.cloud/Enrichr/#libraries
# In[37]:
ov.utils.download_pathway_database()
# In[14]:
pathway_dict=ov.utils.geneset_prepare('genesets/WikiPathways_2019_Mouse.txt',organism='Mouse')
# Note that the `pvalue_type` we set to `auto`, this is because when the genesets we enrichment if too small, use the `adjusted pvalue` we can't get the correct result. So you can set `adjust` or `raw` to get the significant geneset.
#
# If you didn't have internet, please set `background` to all genes expressed in rna-seq,like:
#
# ```python
# enr=ov.bulk.geneset_enrichment(gene_list=deg_genes,
# pathways_dict=pathway_dict,
# pvalue_type='auto',
# background=dds.result.index.tolist(),
# organism='mouse')
# ```
# In[15]:
deg_genes=dds.result.loc[dds.result['sig']!='normal'].index.tolist()
enr=ov.bulk.geneset_enrichment(gene_list=deg_genes,
pathways_dict=pathway_dict,
pvalue_type='auto',
organism='mouse')
# To visualize the enrichment, we use `geneset_plot` to finish it
# In[21]:
ov.bulk.geneset_plot(enr,figsize=(2,5),fig_title='Wiki Pathway enrichment',
cax_loc=[2, 0.45, 0.5, 0.02],
bbox_to_anchor_used=(-0.25, -13),node_diameter=10,
custom_ticks=[5,7],text_knock=3,
cmap='Reds')
# ## Multi pathway enrichment
#
# In addition to pathway enrichment for a single database, OmicVerse supports enriching and visualizing multiple pathways at the same time, which is implemented using [`pyComplexHeatmap`](https://dingwb.github.io/PyComplexHeatmap/build/html/notebooks/gene_enrichment_analysis.html), and Citetation is welcome!
# In[22]:
pathway_dict=ov.utils.geneset_prepare('genesets/GO_Biological_Process_2023.txt',organism='Mouse')
enr_go_bp=ov.bulk.geneset_enrichment(gene_list=deg_genes,
pathways_dict=pathway_dict,
pvalue_type='auto',
organism='mouse')
pathway_dict=ov.utils.geneset_prepare('genesets/GO_Molecular_Function_2023.txt',organism='Mouse')
enr_go_mf=ov.bulk.geneset_enrichment(gene_list=deg_genes,
pathways_dict=pathway_dict,
pvalue_type='auto',
organism='mouse')
pathway_dict=ov.utils.geneset_prepare('genesets/GO_Cellular_Component_2023.txt',organism='Mouse')
enr_go_cc=ov.bulk.geneset_enrichment(gene_list=deg_genes,
pathways_dict=pathway_dict,
pvalue_type='auto',
organism='mouse')
# In[167]:
enr_dict={'BP':enr_go_bp,
'MF':enr_go_mf,
'CC':enr_go_cc}
colors_dict={
'BP':ov.pl.red_color[1],
'MF':ov.pl.green_color[1],
'CC':ov.pl.blue_color[1],
}
ov.bulk.geneset_plot_multi(enr_dict,colors_dict,num=3,
figsize=(2,5),
text_knock=3,fontsize=8,
cmap='Reds'
)
# In[166]:
def geneset_plot_multi(enr_dict,colors_dict,num:int=5,fontsize=10,
fig_title:str='',fig_xlabel:str='Fractions of genes',
figsize:tuple=(2,4),cmap:str='YlGnBu',
text_knock:int=5,text_maxsize:int=20,ax=None,
):
from PyComplexHeatmap import HeatmapAnnotation,DotClustermapPlotter,anno_label,anno_simple,AnnotationBase
for key in enr_dict.keys():
enr_dict[key]['Type']=key
enr_all=pd.concat([enr_dict[i].iloc[:num] for i in enr_dict.keys()],axis=0)
enr_all['Term']=[ov.utils.plot_text_set(i.split('(')[0],text_knock=text_knock,text_maxsize=text_maxsize) for i in enr_all.Term.tolist()]
enr_all.index=enr_all.Term
enr_all['Term1']=[i for i in enr_all.index.tolist()]
del enr_all['Term']
colors=colors_dict
left_ha = HeatmapAnnotation(
label=anno_label(enr_all.Type, merge=True,rotation=0,colors=colors,relpos=(1,0.8)),
Category=anno_simple(enr_all.Type,cmap='Set1',
add_text=False,legend=False,colors=colors),
axis=0,verbose=0,label_kws={'rotation':45,'horizontalalignment':'left','visible':False})
right_ha = HeatmapAnnotation(
label=anno_label(enr_all.Term1, merge=True,rotation=0,relpos=(0,0.5),arrowprops=dict(visible=True),
colors=enr_all.assign(color=enr_all.Type.map(colors)).set_index('Term1').color.to_dict(),
fontsize=fontsize,luminance=0.8,height=2),
axis=0,verbose=0,#label_kws={'rotation':45,'horizontalalignment':'left'},
orientation='right')
if ax==None:
fig, ax = plt.subplots(figsize=figsize)
else:
ax=ax
#plt.figure(figsize=figsize)
cm = DotClustermapPlotter(data=enr_all, x='fraction',y='Term1',value='logp',c='logp',s='num',
cmap=cmap,
row_cluster=True,#col_cluster=True,#hue='Group',
#cmap={'Group1':'Greens','Group2':'OrRd'},
vmin=-1*np.log10(0.1),vmax=-1*np.log10(1e-10),
#colors={'Group1':'yellowgreen','Group2':'orange'},
#marker={'Group1':'*','Group2':'$\\ast$'},
show_rownames=True,show_colnames=False,row_dendrogram=False,
col_names_side='top',row_names_side='right',
xticklabels_kws={'labelrotation': 30, 'labelcolor': 'blue','labelsize':fontsize},
#yticklabels_kws={'labelsize':10},
#top_annotation=col_ha,left_annotation=left_ha,right_annotation=right_ha,
left_annotation=left_ha,right_annotation=right_ha,
spines=False,
row_split=enr_all.Type,# row_split_gap=1,
#col_split=df_col.Group,col_split_gap=0.5,
verbose=1,legend_gap=10,
#dot_legend_marker='*',
xlabel='Fractions of genes',xlabel_side="bottom",
xlabel_kws=dict(labelpad=8,fontweight='normal',fontsize=fontsize+2),
# xlabel_bbox_kws=dict(facecolor=facecolor)
)
tesr=plt.gcf().axes
for ax in plt.gcf().axes:
if hasattr(ax, 'get_xlabel'):
if ax.get_xlabel() == 'Fractions of genes': # 假设 colorbar 有一个特定的标签
cbar = ax
cbar.grid(False)
if ax.get_ylabel() == 'logp': # 假设 colorbar 有一个特定的标签
cbar = ax
cbar.tick_params(labelsize=fontsize+2)
cbar.set_ylabel(r'$−Log_{10}(P_{adjusted})$',fontsize=fontsize+2)
cbar.grid(False)
return ax
# In[ ]: