对于第一种情况,代码编辑器中的中文跟
编辑器的编码
有关,因此可能会出现在编辑器中能够显示的中文,但是到了Qt的UI界面中就出现了乱码,例如
1 2 3
QString status = "echo 测试 && pause" ; ui.textEdit->setText (status);
原因: Visual Studio中对中文的默认编码和QT对中文的默认编码不一样。也就是说,我们输入了X编码方案的中文,但是在编译阶段,Qt用了Y编码方案进行解码,从而导致源码阶段的乱码。
解决方案,就是设置好编码。
1 2 3 4 5 6
QString status = QString::fromLocal8Bit ("echo 测试 && pause" ); ui.textEdit->setText (status); QString status = fromUtf16 (u"echo 测试 && pause" ); ui.textEdit->setText (status);
对于第二种情况,QString获取到的中文就是它默认的编码方式,因此通过文件选择框获取的文件路径,如果包含中文,它也能够在Qt的UI界面正常展示。
但是如果直接转成string,然后调用system就会出现乱码,如
1 2 3 4
QString status = QString::fromUtf16 (u"echo 测试 && pause" ); string test = status.toStdString (); system (test.c_str ());
即,QString转string的时候存在编码上的问题。
解决方案, 将QString转成Loal8Bit才行,而不是直接使用toStdString,之后在构建成string,转成const char*才能避免乱码。
1 2 3
QString status = QString::fromUtf16 (u"echo 测试 && pause" ); string test (status.toLocal8Bit()) ;system (test.c_str ());
https://cloud.tencent.com/developer/article/1464366
彻底解决Qt中文乱码以及汉字编码的问题(UTF-8/GBK)
借Qt中文乱码谈谈Coding中的编码问题
1 2
int a = 1 ;int *ptr = &a;
常量指针(const pointer), 指针本质上是个变量,因此可以用
const
进行修饰,表示该指针记录的值是一个常量。常量指针在声明时需要初始化值。
1 2
int a=1 ;int *const ptr = &a;
指向常量的指针(pointer refer to const)
1 2 3
int const a = 1 ;int cont *ptr = &a;
指向常量的常量指针
这是我第一次在号称宇宙最强的IDE Visual Studio上调用非标准库编译
C++
程序,中间遇到了很多的报错,让我怀疑人生。
首先,我们需要从
Sourceforge
下载OpenCV, 目前最新版是4.5.2
下载的exe文件双击之后会出现解压界面
解压缩后得到如下文件
我们需要依次系统属性->高级->环境变量,找到并设置设置环境变量Path
如果不在环境变量中设置opencv中的bin路径,会出现如下报错 【由于找不到opencv_world452d.dll, 无法继续执行代码】
在Visual Studio 2019中使用OpenCV构建项目的流程如下
第一步:新建一个C++的控制台项目。
第二步:配置项目的项目名称,例如opencv-test
创建项目之后,先将Debug 改为x64,因为后续构建的是x64的项目。
第三步:为了能让代码正常运行,我们需要配置这个OpenCV项目的所需的include和library路径,以及依赖的lib文件。
在菜单栏的项目(P)中选择属性(P)
选择VC++目录(VC++ Directories)的包含目录(Include Directories),点击编辑
添加opencv的include的路径(头文件)
同样的操作,也用于库目录(Library Directories)的设置
添加library路径(路径比较深)
检查下,刚刚修改的include和library
此外还需要增加一个包括所有模块的lib文件。选择链接器(linker)中的输入(input), 接着编辑附加依赖项
![linker(
https://halo-1252249331.cos.ap-shanghai.myqcloud.com/upload/2021/05/image-75a058ac43214ee9bfb9fb18f884df75.png
)
添加
opencv_world452d.lib
,该文件包括opencv里的所有模块(lib文件和opencv版本有关,可从lib目录中确认)。
如果不设置该变量,会出现【无法解析外部符号】的报错
如果写错成 opencv_world452d.dll,就会出现【 LNK1104 无法打开文件”opencv_world452d.dll”】报错(之所以写成dll,是因为之前出现的dll找不到报错,导致我以为增加的是这个文件)。
如下是测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace cv;using namespace std;int main () { Mat image = Mat::zeros (600 , 600 , CV_8UC3); putText (image, "xuzhougeng" , Point (100 ,300 ), FONT_HERSHEY_COMPLEX, 2.0 , Scalar (100 ,200 ,200 ), 5 ); imshow ("Display Window" , image); waitKey (0 ); return 0 ; }
能正常出图表示能正确在项目中调用OpenCV。
参考资料:
https://docs.opencv.org/master/d3/d52/tutorial_windows_install.html
https://medium.com/@subwaymatch/opencv-410-with-vs-2019-3d0bc0c81d96
Slurm的安装依赖于root权限
1 2 3 4 5
wget https://github.com/dun/munge/releases/download/munge-0.5.14/munge-0.5.14.tar.xz rpmbuild -tb --without verify munge-0.5.14.tar.xz cd /root/rpmbuild/RPMS/x86_64rpm -ivh munge-0.5.14-1.el7.x86_64.rpm \ munge-devel-0.5.14-1.el7.x86_64.rpm munge-libs-0.5.14-1.el7.x86_64.rpm
https://www.schedmd.com/downloads.php
因为是CentOS7, 因此我下载的是19.05版本。 而20.11可能不再支持Python2。
1 2 3 4 5 6
wget https://download.schedmd.com/slurm/slurm-19.05.8.tar.bz2 yum install pam-devel perl-Switch -y rpmbuild -ta slurm-19.05.8.tar.bz2 cd /root/rpmbuild/RPMS/x86_64rpm --install slurm-*.rpm
创建用户 slurm
创建配置文件(非常关键)
1 2
mkdir -p /etc/slurmtouch /etc/slurm/slurm.conf
etc中slurm.conf文件里面的配置信息来自于
https://slurm.schedmd.com/configurator.html
生成,需要配置如下选项
SlurmctldHost: 信息来自于
hostname -f
NodeName: 信息来自于
hostname -f
, 只不过是子节点的服务器信息,如果只有单个主机,那么同上
ComputeNodeAddress: 计算节点的IP地址,仅有单个节点时,信息为空
PartitionName: 任务分配名,改成batch
CPUs: 设置为空
CoresPerSocket: 实际的物理CPU数,例如96
ThreadsPerCore: 如果超线程,设置为2
RealMemory: 服务器内存大小,单位为Mb
SlurmUser: slurm要求有一个专门的用户,
StateSaveLocation: 一定要改成 /var/spool/slurmd, 否则会出现权限问题
最后还需要增加一行
CgroupMountpoint=/sys/fs/cgroup
启动 slurmctld, slurmd 的守护进程(deamon)
1 2 3 4 5 6 7 8
systemctl enable slurmctld systemctl start slurmctld systemctl status slurmctld systemctl enable slurmd systemctl start slurmd systemctl status slurmd
https://slurm.schedmd.com/configurator.html
填写 “Compute Machines” 的硬件信息出现错误
第二个error原因是配置文件的默认配置表现不佳,需要做如下替换
1
echo CgroupMountpoint=/sys/fs/cgroup >> /etc/slurm/cgroup.conf
参考:
https://stackoverflow.com/questions/62641323/error-cgroup-namespace-freezer-not-mounted-aborting
https://slurm.schedmd.com/configurator.html
单节点slurm:
http://docs.nanomatch.de/technical/SimStackRequirements/SingleNodeSlurm.html
munge配置:
https://github.com/dun/munge/wiki/Installation-Guide
Slurm安装与使用:
http://wiki.casjc.com/?p=378
最近有一个需求,计算250条序列两两之间的相似度,之后根据相似度继续进行序列过滤,即A和B如果相似度高于一个阈值,那么就把B去掉。
我最初想到的就是在Python里面调用EMBOSS的needle,准备使用Python的os或者subprocess模块,但是突然想到之前看WGDI源代码时,发现作者时通过biopython的API进行MAFFT的调用,于是就决定改用Biopython.
通过查找文档,我找到了Biopython对这部分内容的介绍,见
http://biopython.org/DIST/docs/tutorial/Tutorial.html#sec97
,示例代码如下
1 2 3 4 5 6 7
from Bio.Emboss.Applications import NeedleCommandlineneedle_cline = NeedleCommandline(asequence="alpha.faa" , bsequence="beta.faa" , gapopen=10 , gapextend=0.5 , outfile="needle.txt" ) stdout, stderr = needle_cline() align = AlignIO.read("needle.txt" , "emboss" )
但是这个代码距离我最终代码还有很长的路要走,因为我需要先将序列写出到文件,然后调用命令行,然后再读取输出文件。我的问题是,能不能省掉这几次I/O操作。在Emboss文档的下面,我发现Biopython提供了两个模块,分别是Bio.pairwise2和Bio.Align.PairwiseAligner, 可以直接使用Biopython的.SeqRecord对象。按照文档描述,pairwise2和PairwiseAligner能够达到和调用EMBOSS相同的速度,经过我测试,发现两者速度的确差别不大,这说明直接在Python里面进行配对序列联配并不比先输出运行所需文件,然后读取运行生成文件这个流程快,所以经过一番折腾之后,我还是决定使用NeedleCommandline。
为了方便后续调用,我写了一个函数,函数的前3个参数是用来从SeqRecord列表中提取序列用于写出,第4个参数用来提供needle程序的路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
def run_needle (aseq_pos, bseq_pos, seq, needle_path, verbose=False ): """run EMBOSS needle retrun align """ aseq = seq[aseq_pos] bseq = seq[bseq_pos] aseq_file = mkstemp(suffix=".fas" )[1 ] bseq_file = mkstemp(suffix=".fas" )[1 ] needle_file = mkstemp(suffix=".needle" )[1 ] SeqIO.write(aseq, aseq_file, "fasta" ) SeqIO.write(bseq, bseq_file, "fasta" ) if needle_path is None : needle_cmd = NeedleCommandline( asequence=aseq_file, bsequence=bseq_file, gapopen=10 , gapextend=0.5 , outfile=needle_file) else : assert os.path.isfile(needle_path) needle_cmd = NeedleCommandline( needle_path, asequence=aseq_file, bsequence=bseq_file, gapopen=10 , gapextend=0.5 , outfile=needle_file) stdout, stderr = needle_cmd() if verbose: print (stdout + stderr, file = sys.stderr) align = AlignIO.read(needle_file, "emboss" ) os.unlink(aseq_file) os.unlink(bseq_file) os.unlink(needle_file) return align
在写这个函数时,我在输出文件的文件名上折腾了很长时间,最初想使用原序列的ID,但ID包括一些奇奇怪怪的字符,例如
(|:
, 而NeedleCommandline不会自动在构建的命令中增加引号,使得运行时会出错。(你可以试试
echo a(b
会出现什么情况 )
后来,我使用了随机数作为文件名。这个方法在单个进程时问题不大,当时当我为了加速使用多进程时,却发现发现随机数重复了。进程A输出的文件A由于和进程B的输入文件名一样,导致被跑完的进程B删了。当然,解决方法也很简单,加上一些判断文件是否存在的ifelse语句即可。
不过,我还是选择调用tempfile标准库,使用mkstemp获取临时文件名,才解决了输出文件名的危机。
最终我就可以在循环中调用这个函数,然后将结果保存在列表中,用于后续处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
fasta = "/path/to/your/sequence.fasta" seqs = [ fas for fas in SeqIO.parse(fasta, "fasta" ) ] needle_path = "/opt/biosoft/EMBOSS-6.6.0/bin/needle" align_res = [] for i in range (len (seqs)): for j in range (i+1 , len (seqs)): align = run_needle(i, j, seqs , needle_path) align_res.append(align ) outfile = open ("pairwise_stats.txt" , "w" ) for align in align_res: line = get_psa_stat(align) line = "\t" .join(line) + "\n" outfile.write(line) outfile.close()
根据我的计算,循环要运行3万多次,按照平均1s一个循环,只要500多分钟,小于9个小时,我只要在回去前运行这个程序(写完第一版大概是晚上10点),然后第二天早上过来收结果就行了。
但是,正如前文提及到的,「该程序会在多个进程运行时报错」,你也就知道我没有跑循环,而是选择了通过并行对循环进行加速。在一篇中,我将会讲一个,如何把一个简单的问题复杂化,最终又回到最初代码的故事
最近总觉得Github的访问速度变慢了,导致我的工作效率也肉眼可见的降低了,主要体现在代码数量和质量的双重降低。
为了解决这一问题,我通过网络检索找到了一个非常好的工具,叫做dev-sidecar (
https://github.com/docmirror/dev-sidecar
), 这个工具的好处在于,图形化界面,完美解决了windows和MacOS上的问题,但是问题也出在图形化界面上,这意味着没有配置图形界面的Linux就用不了。
但是这难不倒我们,因为我看到了这个工具的参考部分。
从中, 我们可以看到一个非常重要的地址,fastgit, 这是一个对于 GitHub.com 的镜像加速器。它的使用方法及其简单,也就是将原来的github.com替换成 hub.fastgit.org即可。
以 bioconda/bioconda-recipes为例,在使用原版的GitHub时,我们的下载速度基本上维持在2MiB/s,某些时候可能不到100Kb.
1 2 3 4 5 6 7 8 9 10
$ time git clone https://github.com/bioconda/bioconda-recipes Cloning into 'bioconda-recipes' ... remote: Enumerating objects: 64, done . remote: Counting objects: 100% (64/64), done . remote: Compressing objects: 100% (50/50), done . remote: Total 276716 (delta 30), reused 31 (delta 11), pack-reused 276652 Receiving objects: 100% (276716/276716), 303.49 MiB | 3.72 MiB/s, done
. Resolving deltas: 100% (152345/152345), done . Checking out files: 100% (17906/17906), done . git clone https://github.com/bioconda/bioconda-recipes 46.51s user 7.04s system 53% cpu 1:39.24 total
但是使用fastgit加速之后,我的下载速度直接飙升到10Mib/s以上,峰值可以达到30Mib/s.
1 2 3 4 5 6 7 8 9 10
$ time git clone https://hub.fastgit.org//bioconda/bioconda-recipes Cloning into 'bioconda-recipes' ... remote: Enumerating objects: 64, done . remote: Counting objects: 100% (64/64), done . remote: Compressing objects: 100% (50/50), done . remote: Total 276716 (delta 30), reused 31 (delta 11), pack-reused 276652 Receiving objects: 100% (276716/276716), 303.23 MiB | 21.16 MiB/s, done . Resolving deltas: 100% (152348/152348), done . Checking out files: 100% (17906/17906), done . git clone https://hub.fastgit.org//bioconda/bioconda-recipes 44.88s user 6.09s system 101% cpu 50.367 total
速度的提升可能是其次的,最重要的是原本因为网络问题的fatal error导致根本下载不了的repos,现在起码能保证能克隆到本地了,实现了从0到1的进步。
当然,如果觉得每次都需要替换URL太过麻烦,fastgit还支持直接修改Git的配置,即
1 2
git config --global url."https://hub.fastgit.org/" .insteadOf "https://github.com/" git config --global protocol.http.allow always
之后,原本需要从Github上克隆的资源都会被定向到fastgit上,不再需要手动进行修改了。
不过这一缺陷在于,部分时候镜像站点可能会出现不可用的情况,此时你从Github克隆时依旧会被改向到镜像站点,你会误以为原站点出现了问题。不过只要我们人人都去支持下这个项目,随着可用节点的增多,这一缺陷也不是问题了。
在上一篇教程的最后,我写道「我们能够更加直观的观察到2个peak,基本确定2个多倍化事件」。这里就引出了一个问题,为什么我们可以根据peak来推断多倍化时间?在Lynch和Conery在2000年发表在Science的论文中,他们证明了小规模基因复制的Ks分布是L型,而在L型分布背景上叠加的峰则是来自于演化历史中某个突然的大规模复制事件。例如下图a中,实线是小规模复制的L型分布(呈指数分布, exponential distribution), 最初的峰可能是近期的串联复制引起,随着时间推移基因丢失,形成一个向下的坡。另一条虚线中的峰(呈正态分布, normal distribution)则是由全基因组复制引起。而b-h是一些物种的ks分布。
注,Lynch和Conery这两人是最早一批研究真核基因组的复制基因的总体保留和丢失情况的研究者。
也就是说,我们可以通过对Ks频率分布图的观察来判断物种在历史上发生的基因组复制事件。同时又因为WGD在Ks频率分布图中表现为正态分布,那么我们可以通过对峰进行拟合来得到WGD事件所对应的Ks值。
使用WGDI对峰进行拟合需要注意的是,
它一次只能拟合一个峰
,因此我们需要先通过之前Ks可视化中所用到kspeaks模块(-kp)来过滤,接着用
PeaksFit
(-pf)模块对峰进行拟合得到模型参数,最后用KsFigures(-kf)将拟合结果绘制到一张图上。
过滤的目的是筛选出同一个WGD事件所形成的共线性区块,这可以通过设置kspeaks模块中和过滤有关的参数来实现
pvalue: 共线性区块的显著性
tandem: 是否过滤串联重复基因
block_length: 共线性区块的基因对的数目
ks_area: 根据 ks_median 筛选给定区间的共线性区块
multiple: 选择homo的哪列作为筛选标准
homo: 根据homo,筛选给定区间内的共线性区块对
其中比较关键的是ks_area 和homo,mutiple, 前者确定ks的大致区间,后者则是更精细地筛选共线性区块。block_length可以过滤掉一些比较小的共线性区块,毕竟基因数越多,就越不可能是随机事件所产生的共线性。
通过观察之前Ks频率分布图,我们大致确定两个峰所对应的区间分别是0
1.25,1.25
2.5。
我们分别用
wgdi -kp \? > peak1.conf
和
wgdi -kp \? > peak2.conf
创建两个文件,主要修改其中的ks_area, homo都设置为-1,1 表示不筛选
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
[kspeaks] blockinfo = ath_block_information.csvpvalue = 0.05 tandem = true block_length = 5 ks_area = 0 ,1.25 multiple = 1 homo = -1 ,1 fontsize = 9 area = 0 ,2 figsize = 10 ,6.18 savefig = ath.ks_peak1.distri.pdfsavefile = ath.ks_peak1.distri.csv[kspeaks] blockinfo = ath_block_information.csvpvalue = 0.05 tandem = true block_length = 5 ks_area = 1.25 ,2.5 multiple = 1 homo = -1 ,1 fontsize = 9 area = 0 ,2 figsize = 10 ,6.18 savefig = ath.ks_peak2.distri.pdfsavefile = ath.ks_peak2.distri.csv
运行
wgdi -kp peak1.conf
和
wgdi -kp peak.conf
输出结果。下图中左是peak1, 右是peak2.
得到这个图之后,我们还可以进一步绘制Ks点阵图, 使用
wgdi -bk >>peak1.conf
和
wgdi -bk >> peak2.conf
增加配置信息,然后对其进行修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
[blockks] lens1 = ath.lenlens2 = ath.lengenome1_name = Athalianagenome2_name = Athalianablockinfo = ath.ks_peak1.distri.csvpvalue = 0.05 tandem = true tandem_length = 200 markersize = 1 area = 0 ,2 block_length = 5 figsize = 8 ,8 savefig = ath.ks_peak1_dotplot.pdf[blockks] lens1 = ath.lenlens2 = ath.lengenome1_name = Athalianagenome2_name = Athalianablockinfo = ath.ks_peak2.distri.csvpvalue = 0.05 tandem = true tandem_length = 200 markersize = 1 area = 0 ,2 block_length = 5 figsize = 8 ,8 savefig = ath.ks_peak2_dotplot.pdf
运行
wgdi -bk peak1.conf
,和
wgdi -bk peak2.conf
输出结果。下图中,左边是peak1,右边是peak2.
由于我们设置的是 homo=-1,1 因此只是根据共线性块的Ks中位数筛选不同的peak,如果需要更加精细的挑选给定Ks中位数范围内的共线性区块,可以尝试修改homo值再观察结果。
homo值表示的共线性区块中基因对的匹配情况,越接近于1,越有可能是近期WGD事件得到的基因对,越接近-1,越有可能是古老WGD事件得到的基因对。
接着,我们将用blockks步骤输出的ath.ks_peak1.distri.csv和tah.ks_peak2.distri.csv 作为peakfit模块的输入,用于拟合。
分别用
wgdi -pf \? >> peak1.conf
和
wgdi -pf \? >> peak2.conf
创建配置文件, 主要修改blockinfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
[peaksfit] blockinfo = ath.ks_peak1.distri.csvmode = medianbins_number = 200 ks_area = 0 ,10 fontsize = 9 area = 0 ,3 figsize = 10 ,6.18 savefig = ath.ks_peak1_peaksfit.pdf [peaksfit] blockinfo = ath.ks_peak2.distri.csvmode = medianbins_number = 200 ks_area = 0 ,10 fontsize = 9 area = 0 ,3 figsize = 10 ,6.18 savefig = ath.ks_peak2_peaksfit.pdf
分别运行
wgdi -pf peak1.conf
和
wgdi -pf peak2.conf
, 会得到拟合的图,以及拟合得到参数
peak1拟合参数
1 2 3
R-square: 0.9804748699350867 The gaussian fitting curve parameters are : 5.02360835744403 | 0.8319599832352784 | 0.10382203381206191
peak2拟合参数
1 2 3
R-square: 0.9188261142099129 The gaussian fitting curve parameters are : 2.084853812322066 | 1.8332872127128195 | 0.2506813629824027
拟合参数将会用于后续的 ksfigure 模块。
我们新建一个 all_ks.csv文件, 该文件的第一行为标题行,第二行以后为数据行。一共有4+3n列,其中第一列是样本信息,第2-3列对应线条的属性,后面都是拟合参数
1 2
,color,linewidth,linestyle,,,,,, ath_ath,green,1,--,5.02360835744403,0.8319599832352784,0.10382203381206191,2.084853812322066,1.8332872127128195,0.2506813629824027
注意,在终端里面编辑时,需要记住linestyle后面的逗号数量是 3n个, 其中n是最大peak数,例如拟南芥有2个peak,那么就得有6个逗号。
假如,我们之前用wgdi拟合过其他物种的peak,也得到了一些拟合参数,那么添加到这个文件中,例如
1
2 3 4 5
,color,linewidth,linestyle,,,,,, ath_ath,red,1,--,5.02360835744403,0.8319599832352784,0.10382203381206191,2.084853812322066,1.8332872127128195,0.2506813629824027 vvi_vvi,yellow,1,-,3.00367275,1.288717936,0.177816426 vvi_oin_gamma,orange,2,-,1.910418336,1.328469514,0.262257112 vvi_oin,green,1,-,4.948194212,0.882608858,0.10426
最后我们用
wgdi -kf >> ath.conf
, 创建配置文件并进行修改
1 2 3 4 5 6 7 8 9 10
[ksfigure] ksfit = all_ks.csvlabelfontsize = 15 legendfontsize = 15 xlabel = noneylabel = nonetitle = nonearea = 0 ,4 figsize = 10 ,6.18 savefig = all_ks.pdf
运行
wgdi -kf ath.conf
得到下图
最后,对这篇教程进行总结。
我们依次使用 wgdi -kp 过滤共线性区块, wgdi -pf 对峰进行拟合, wgdi -kf 展示最后的拟合结果
共线性区块的过滤是一个精细的工作,可以尝试设置不同的homo范围观察峰的变化来确定参数是否合理
chr1
,
start1
,
end1
即参考基因组(点图的左边)的共线性范围(对应GFF1的位置)
chr2
,
start2
,
end2
即参考基因组(点图的上边)的共线性范围(对应GFF2的位置)
pvalue
即共线性结果评估,常常认为小于0.01的更合理些
length
即共线性片段中基因对数目
ks_median
即共线性片段上所有基因对
ks
的中位数(主要用来评判ks分布的)
ks_average
即共线性片段上所有基因对
ks
的平均值
block1
,
block2
分别为共线性片段上基因
order
的位置。
ks
共线性片段上所有基因对的
ks
值
density1
,
density2
共线性片段的基因分布密集程度。值越小表示稀疏。
最后两列,
class1
和
class2
会在 alignment 模块中用到,对应的是两个block分组,默认值是0表示两个block是同一组。这两列后期需要自己根据覆盖率,染色体核型等多个方面进行确定。举个例子,我们可以根据 homo1 的取值范围对class1进行赋值,例如-1
-0.5 是 1,-0.5 ~ 0.5 是2,0.5
1是3,最后在alignment中会就会用三种颜色来展示,例如下图的1,2,3分别对应red,blue,green.
中间的
homo1
,
homo2
,
homo3
,
homo4
,
homo5
并非那么直观,先说结论:
这里的homoN(N=1,2,3,4,5) 表示一个基因有N个最佳匹配时的取值
N由mutiple参数确定,对应点阵图(dotplot)中的红点
multiple的取值一般取1即可,表示最近一次的WGD可能是一次二倍化事件,因此每个基因只会有一个最佳匹配。如果设置为2,可能是一次3倍化,每个基因由两个最佳匹配。当然实际情况可能会更加复杂,比如说异源四倍体,或者异源六倍体,或者没有多倍化只是小规模的基因复制(small-scale gene duplication) 等情况,也会影响multiple的设置。
homoN会在后面过滤共线性区块时用到,一般最近的WGD事件所产生的共线性区块会比较接近1,而古老的WGD产生的共线性区块则接近-1.
接着,我们将根据源代码
blast_homo
和
blast_position
来说明结算过程。
首先需要用到blast_homo函数,用来输出每个基因对在不同最佳匹配情况下的取值(-1,0,1)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
def blast_homo (self, blast, gff1, gff2, repeat_number ): index = [group.sort_values(by=11 , ascending=False )[:repeat_number].index.tolist() for name, group in blast.groupby([0 ])] blast = blast.loc[np.concatenate( np.array([k[:repeat_number] for k in index], dtype=object )), [0 , 1 ]] blast = blast.assign(homo1=np.nan, homo2=np.nan, homo3=np.nan, homo4=np.nan, homo5=np.nan) for i in range (1 , 6 ): bluenum = i+5 redindex = np.concatenate( np.array([k[:i] for k in index], dtype=object )) blueindex = np.concatenate( np.array([k[i:bluenum] for k in index], dtype=object )) grayindex = np.concatenate( np.array([k[bluenum:repeat_number] for k in index], dtype=object )) blast.loc[redindex, 'homo' +str (i)] = 1 blast.loc[blueindex, 'homo' +str (i)] = 0 blast.loc[grayindex, 'homo' +str (i)] = -1 return blast
for循环前的代码作用是提取每个基因BLAST后的前N个最佳结果。循环的作用基因对进行赋值,主要规则是基因对如果在点图中为
红色
,赋值为1,
蓝色
赋值为0,
灰色
赋值为-1。
homo1 对应 redindex = 0:1, bluenum = 1:6, grayindex = 6:repeat_number
homo2 对应redindex = 0:2, bluenum = 2:7, grayindex = 7:repeat_number
homo5对应redindex=0:5, bluenum=5:10, grayindex = 10:repeat_number
最终函数返回的就是每个基因对,在不同最佳匹配数下的赋值结果。
1 2 3 4 5 6 7 8 9 10 11 12 13
0 1 homo1 homo2 homo3 homo4 homo5 185893 AT1G01010 AT4G01550 1.0 1.0 1.0 1.0 1.0 185894 AT1G01010 AT1G02230 0.0 1.0 1.0 1.0 1.0 185899 AT1G01010 AT4G35580 -1.0 0.0 0.0 0.0 0.0 185900 AT1G01010 AT1G33060 -1.0 -1.0 0.0 0.0 0.0 185901 AT1G01010 AT3G49530 -1.0 -1.0 -1.0 0.0 0.0 185902 AT1G01010 AT5G24590 -1.0 -1.0 -1.0 -1.0 0.0 250822 AT1G01030 AT1G13260 0.0 0.0 0.0 1.0 1.0 250823 AT1G01030 AT1G68840 0.0 0.0 0.0 0.0 1.0 250825 AT1G01030 AT1G25560 0.0 0.0 0.0 0.0 0.0 250826 AT1G01030 AT3G25730 -1.0 0.0 0.0 0.0 0.0 250824 AT1G01030 AT5G06250 -1.0 -1.0 0.0 0.0 0.0
然后block_position函数, 会用
for k in block[1]
的循环提取每个共线性区块中每个基因对的homo值,然后用
df = pd.DataFrame(blk_homo)
和
homo = df.mean().values
求均值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
def block_position (self, collinearity, blast, gff1, gff2, ks ): data = [] for block in collinearity: blk_homo, blk_ks = [], [] if block[1 ][0 ][0 ] not in gff1.index or block[1 ][0 ][2 ] not in gff2.index: continue chr1, chr2 = gff1.loc[block[1 ][0 ][0 ], 'chr' ], gff2.loc[block[1 ][0 ][2 ], 'chr' ] array1, array2 = [float (i[1 ]) for i in block[1 ]], [ float (i[3 ]) for i in block[1 ]] start1, end1 = array1[0 ], array1[-1 ] start2, end2 = array2[0 ], array2[-1 ] block1, block2 = [], [] for k in block[1 ]: block1.append(int (float (k[1 ]))) block2.append(int (float (k[3 ]))) if k[0 ]+"," +k[2 ] in ks.index: pair_ks = ks[str (k[0 ])+"," +str (k[2 ])] blk_ks.append(pair_ks) elif k[2 ]+"," +k[0 ] in ks.index: pair_ks = ks[str (k[2 ])+"," +str (k[0 ])] blk_ks.append(pair_ks) else : blk_ks.append(-1 ) if k[0 ]+"," +k[2 ] not in blast.index: continue blk_homo.append( blast.loc[k[0 ]+"," +k[2 ], ['homo' +str (i) for i in range (1 , 6 )]].values.tolist()) ks_arr = [k for k in blk_ks if k >= 0 ] if len (ks_arr) == 0 : ks_median = -1 ks_average = -1 else : arr_ks = [k for k in blk_ks if
k >= 0 ] ks_median = base.get_median(arr_ks) ks_average = sum (arr_ks)/len (arr_ks) df = pd.DataFrame(blk_homo) homo = df.mean().values if len (homo) == 0 : homo = [-1 , -1 , -1 , -1 , -1 ] blkks = '_' .join([str (k) for k in blk_ks]) block1 = '_' .join([str (k) for k in block1]) block2 = '_' .join([str (k) for k in block2]) data.append([block[0 ], chr1, chr2, start1, end1, start2, end2, block[2 ], len ( block[1 ]), ks_median, ks_average, homo[0 ], homo[1 ], homo[2 ], homo[3 ], homo[4 ], block1, block2, blkks]) data = pd.DataFrame(data, columns=['id' , 'chr1' , 'chr2' , 'start1' , 'end1' , 'start2' , 'end2' , 'pvalue' , 'length' , 'ks_median' , 'ks_average' , 'homo1' , 'homo2' , 'homo3' , 'homo4' , 'homo5' , 'block1' , 'block2' , 'ks' ]) data['density1' ] = data['length' ] / \ ((data['end1' ]-data['start1' ]).abs ()+1 ) data['density2' ] = data['length' ] / \ ((data['end2' ]-data['start2' ]).abs ()+1 ) return data
最终得到的homo1的homo5,是不同最佳匹配基因数下计算的值。如果共线性的点大部分
为红色
,那么该值接近于1;如果共线性的点大部分
为蓝色
,那么该值接近于0;如果共线性的点大部分
为灰色
,那么该值接近于-1。也就是我们可以根据最初的点图中的颜色来确定将来筛选不同WGD事件所产生共线性区块。
这也就是为什么homoN可以作为共线性片段的筛选标准。
如何用WGDI进行共线性分析(一)
得到共线性分析结果和Ks值输出结果的整合表格文件后,我们就可以绘制Ks点阵图和Ks频率分布图对共线性区的Ks进行探索性分析,从而确定可能的Ks峰值,用于后续分析。
ATAC-seq | 单细胞
ATAC-seq | 差异分析
ATAC-seq | 表观组 | ChIP-seq
ATAC-seq | 表观组 | 单细胞
BigWig
BioNano
C/C++
C/C++ | 算法
ChIP-seq
GitHub
Hi-C
JCVI
MacOS
NGS
NGS | 遗传定位
PBMC
Perl | 软件安装
QT | MSVC
Seurat
Seurat | 单细胞 | 数据挖掘
Seurat | 转录组 | 单细胞
Web开发
Zotero | 文献 | 坚果云
biocondutor
conda
samtools
typora
个人博客
单细胞
可视化
可视化 | CIRCOS
可视化 | JCVI
可视化 | 单细胞
可视化 | 比较基因组学
基因家族
基因组
小技巧
小技巧 | SSH
序列比对
数据挖掘
数据结构
数据结构 | C/C++
服务器
正则表达式
正则表达式 | 字符串处理
比较基因组学
水稻 | 转录组
水稻 | 转录组 | 遗传定位
注释
注释 | MAKER
注释 | 序列比对
注释 | 流程工具
注释 | 流程工具 | MAKER
注释 | 重复序列
流程工具
流程工具 | 基因家族
流程工具 | 服务器
深度学习
源码解读
源码解读 | hash
爬虫
环境变量
环境配置 | WSL
算法
系统发育
组装
组装 | Hi-C
组装 | 转录组 | 注释
编程语言
自然语言 | 深度学习
表观组
读书
转录组
转录组 | 单细胞
转录组 | 差异分析 | TCGA
转录组 | 序列比对
软件安装
遗传定位
重复序列
随笔