使用SignalP对蛋白序列进行信号肽预测

1. 信号肽简介

信号肽是蛋白质N-末端一段编码长度为5-30的疏水性氨基酸序列,用于引导新合成蛋白质向通路转移的短肽链。信号肽存在于分泌蛋白、跨膜蛋白和真核生物细胞器内的蛋白中。

信号肽指引蛋白质转移的方式有两种:(1)常规的分泌(Sec/secretory)通路;(2)双精氨酸转移(Tat/twin-arginine)通路。前者存在于原核生物蛋白质转移到质膜过程中,以及真核生物蛋白质转移到内质网膜的过程中。后者存在于细菌、古菌、叶绿体和线粒体中,信号肽序列较长、疏水性较弱且尾部区含有两个连续精氨酸。相比于前者转运非折叠蛋白质,后者能转运折叠蛋白质跨越双层脂质膜 。

信号肽指引蛋白质转运后,将由信号肽酶进行切除。信号肽酶有三种:(1)一型信号肽酶(SPaseI);(2)二型信号肽酶(SPaseII);(3)三型信号肽酶(SPaseIII)。大部分信号肽由SPaseI进行移除,SPaseI存在古菌、细菌和真核生物中,且在真核生物的内质网膜上仅存在一型信号肽酶。细菌和古菌脂蛋白的信号肽C端含有一段称为 lipobox 的保守区域,由SPaseII切除其信号肽,且lipobox紧邻切除位点(CS/Cleavage Site)的氨基酸是半胱氨酸,这和锚定到膜的功能是相关的。细菌的四型菌毛蛋白信号肽由SPaseIII进行切除。此外:分泌通路(Sec)相关信号肽能由SPaseI、SPaseII和SPaseIII切除,但是双精氨酸转移(Tat)通路相关信号肽仅由 SPaseI和SPaseII切除。

使用SignalP 5.0能对原核生物的信号肽Sec/SPI、Sec/SPII和Tat/SPI,和对真核生物仅含有 Sec/SPI信号肽进行预测 。 SignalP 5.0目前不能对Tat/SPII进行预测。此外,由于没有足够大的数据进行训练,SignalP 5.0 也不能对Sec/SPIII进行分析。

SignalP是最为常用的信号肽分析软件,常用于分泌蛋白预测的第一步。到目前2019年4月,SignalP版本到了第5版。第一版本基于人工神经网络(Artificial Neural Network);第二版本引入隐马尔科夫模型(Hidden Markov Models);第三版本改进切除位点(Cleavage site)预测方法;第四版本改进对信号肽和跨膜螺旋的区分能力。这四个版本仅能对Sec/SPI类型的信号肽进行预测。而第五版本结合了深度神经网络(deep neural network)、条件随机分类(Conditional random field classification)和迁移学习(transfer learning)方法,能对信号肽进行更准确的预测。

可以使用SignalP网页工具进行分析。但一次仅支持最多5000条序列。以下讲解本地化运行SignalP软件。

2. SignalP软件下载和安装

# 需要填写edu邮箱和相关信息来获取下载地址
$ wget http://www.cbs.dtu.dk/download/6B91F6BC-5A05-11E9-8172-2ED6B9CD16B5/signalp-5.0.Linux.tar.gz -P ~/software/
$ tar zxf /home/train/software/signalp-5.0.Linux.tar.gz -C /opt/biosoft/
$ echo 'PATH=$PATH:/opt/biosoft/signalp-5.0/bin' >> ~/.bashrc
$ source ~/.bashrc

3. SignalP软件使用

对真核生物的全基因组蛋白序列进行信号肽预测:
$ signalp -batch 30000 -org euk -fasta proteins.fasta -gff3 -mature
signalp命令的参数:

-batch <int> default: 10000
程序并行化运行的序列条数。程序能多线程运行,速度很快。推荐设置该参数值大于FASTA文件的序列总条数,虽然增加内存消耗,但能加快程序运行。
-org <string> default: euk
设置分析的物种类型。该参数值有4种:arch,古菌;gram+,革兰氏阳性细菌,gram-,革兰氏阴性细菌;euk,真核生物。
-fasta <string>
输入FASTA格式的蛋白序列文件。
-prefix <string>
设置输出文件前缀。默认在程序运行目录下输出结果文件,和输入文件名的前缀相同,后缀为_summary.signalp5。
-gff3
添加该参数,输出GFF3格式的信号肽预测结果。
-mature
添加该参数,对含有信号肽的蛋白序列,切除信号肽后输出其成熟蛋白序列。可以用于下游的跨膜区分析。
-tmp <string> default: /tmp
设置临时文件夹路径。
-format <string> default: short
设置输出格式。该参数值有两个:short,仅输出一个信号肽预测的整合文本结果;long,额外输出每条序列的各位点预测文本结果和图片结果;
-plot <string> default: png
设置输出图片结果的类型。当--format参数为long时,该参数生效。该参数值有三个:png;eps;none表示仅得到表格文件。
-version
打印程序版本并退出。

网页服务器禁止IP访问

我的wordpress站点总是有很多垃圾评论。于是需要对相应的IP地址禁止访问。

我的方法是:在/etc/httpd/conf.d目录下生成后缀为多个.conf的文件,每个文件分别对一个目标文件夹进行保护。比如生成文件/etc/httpd/conf.d/deny_chenlianfu.conf,其内容为:

<Directory "/home/chenlianfu/wordpress">
    AllowOverride None
    Options MultiViews FollowSymLinks ExecCGI
    Order allow,deny
    Allow from all
    Deny from 100.42.17.90
    Deny from 101.4.136.34
    Deny from 101.91.215.188
    Deny from 101.98.247.14
    Deny from 95.85.80.227
    Deny from 95.85.80.82
    Deny from 95.85.80.86
    Deny from 98.174.90.36
</Directory>

然后重启httpd服务,使配置文件生效,从而禁止配置文件中的IP访问我的网站。

/etc/init.d/httpd restart

为了对多个文件夹进行保护,则要生成多个配置文件。我编写名为wordpress_deny_ips.pl的程序,输入含有准备禁止访问IP地址的文本文件,自动生成多个配置文件:

#!/usr/bin/perl
use strict;

my $usage = <<USAGE;
USAGE:
    perl $0 web.txt

USAGE
if (@ARGV==0){die $usage}

open IN, "/etc/httpd/conf.d/deny_chenlianfu.conf";
my %ip;
while (<IN>) {
    $ip{$1} = 1 if m/(\d+\.\d+\.\d+\.\d+)/;
}
close IN;

open IN, $ARGV[0] or die "Can not open file $ARGV[0], $!\n";
my %ip_new;
while (<IN>) {
    $ip_new{$1} = 1 if m/(\d+\.\d+\.\d+\.\d+)/;
}
close IN;

my $number = 0;
foreach (keys %ip_new) {
    if (exists $ip{$_}) {
        print STDERR "Duplicate $_\n";
    }
    else {
        $ip{$_} = 1;
        $number ++;
    }
}

my @num = keys %ip;
my $num = @num;
print STDERR "$number ips were add\n$num ips in total\n";

my $out = '
    AllowOverride None
    Options MultiViews FollowSymLinks ExecCGI
    Order allow,deny
    Allow from all
';
foreach (sort keys %ip) {
    $out .= "    Deny from $_\n";
}
$out .= "</Directory>\n";


open OUT, ">", "/etc/httpd/conf.d/deny_chenlianfu.conf" or die "Can not create file /etc/httpd/conf.d/deny_chenlianfu.conf, $!\n";
print OUT '<Directory "/home/chenlianfu/wordpress">' . $out;
close OUT;

open OUT, ">", "/etc/httpd/conf.d/deny_zhengyue.conf" or die "Can not create file /etc/httpd/conf.d/deny_zhengyue.conf, $!\n";
print OUT '<Directory "/home/zhengyue/wordpress">' . $out;
close OUT;

open OUT, ">", "/etc/httpd/conf.d/deny_wuchangsong.conf" or die "Can not create file /etc/httpd/conf.d/deny_wuchangsong.conf, $!\n";
print OUT '<Directory "/home/wuchangsong/wordpress">' . $out;
close OUT;

很多垃圾评论是全英文或含有日文。可以在主体对应的functinons.php文件中添加一些设置来禁止全英文或包含日文的评论。我在文件./wp-content/themes/twentyeleven/functions.php的尾部添加以下代码:

function refused_english_comments( $incoming_comment ) {
    $pattern = '/[一-龥]/u';
    //禁止全英文评论
    if(!preg_match($pattern, $incoming_comment['comment_content'])) {
        wp_die( "您的评论中必须包含汉字!" );
    }

    $pattern = '/[あ-んア-ン]/u';
    //禁止日文评论
    if(preg_match($pattern, $incoming_comment['comment_content'])) {
        wp_die( "评论禁止包含日文" );
    }
    return( $incoming_comment );
}
add_filter('preprocess_comment', 'refused_english_comments');

然后重启网页服务,即可生效。

检测全基因组序列中的端粒序列

使用三代测序数据能获得较好的、甚至完整的基因组序列。通过检测基因组序列两端的属于端粒(Telomere)的特定的重复序列,可以知道基因组组装是否得到完整的染色体水平的序列。若在序列中间检测到端粒序列,可以知道基因组组装过程中对Contigs有错误的连接。

在染色体序列首尾存在端粒序列。在人类中,端粒序列由重复单元TTAGGG,串联重复约2500次组成。 不同的物种,端粒的重复单元可能不一样,可以在端粒数据库中查询。 我对一种子囊菌使用PacBio测序数据进行了基因组组装,得到12条序列,发现大部分序列首尾均出现了TTAGGG/CCCTAA的串联重复序列。我对一种昆虫物种PacBio组装基因组序列进行分析,发现序列首尾出现一些长度较长微卫星重复序列,而没有固定的重复单元,这和端粒数据库中的结果一致。

编写Perl程序对全基因组序列的端粒序列进行搜索,查看基因组序列的完整情况:

#!/usr/bin/perl
use strict;
use Getopt::Long;

my $usage = <<USAGE;
Usage:
    $0 genome.fasta > telomere_info.txt

    大部分物种端粒序列的重复单元是TTAGGG/CCCTAA。本程序能在基因组中寻找端粒重复单元的串联重复序列,并给出位点信息。

    --split-length <int>    default: 100000
    --overlap-length <int>    default: 10000
    程序会将每条序列打断后进行重复单元搜索。这两个参数设置打断的序列长度和相邻两序列之间的重叠长度。

    --repeat-unit <string>    default: TTAGGG
    设置重复单元碱基序列,该重复单元的反向互补也将作为重复单元进行搜索。可以在端粒数据库(http://telomerase.asu.edu/sequences_telomere.html)中寻找目标端粒重复单元。
    vertebrate sp.      TTAGGG
    plants sp.          TTTAGGG
    Pezizomycotina      TTAGGG

    --min-repeat-num <int>    default: 4
    设置重复单元最小重复次数。


USAGE
if (@ARGV==0){die $usage}

my ($splitLength, $overlapLength, $repeatunit, $minRepeatNum);
GetOptions(
    "split-length:i" => \$splitLength,
    "overlap-length:i" => \$overlapLength,
    "repeat-unit:s" => \$repeatunit,
    "min-repeat-num:s" => \$minRepeatNum,
);
$splitLength ||= 100000;
$overlapLength ||= 10000;
$repeatunit ||= "TTAGGG";
$repeatunit = uc($repeatunit);
my $repeatunit_reverse = reverse $repeatunit;
$repeatunit_reverse =~ tr/ATCG/TAGC/;
$minRepeatNum ||= 4;

# 读取基因组序列
open IN, $ARGV[0] or die "Can not open file $ARGV[0], $!\n";
my (%seq, $seq_id);
while (<IN>) {
    chomp;
    if (m/^>(\S+)/) {
        $seq_id = $1;
    }
    else {
        $_ = uc($_);
        $seq{$seq_id} .= $_;
    }
}
close IN;

# 将基因组序列打断
my (%seq_split, %seq_length);
foreach my $id (keys %seq) {
    my $seq = $seq{$id};
    my $length = length($seq);
    $seq_length{$id} = $length;
    my $pos = 0;
    while ($pos < $length) {
        $seq_split{$id}{$pos} = substr($seq, $pos, $splitLength + $overlapLength);
        $pos += $splitLength;
    }
}

print "SeqID\tSeqLength\tStart\tEnd\tLength\tType\n";
foreach my $id (sort keys %seq_split) {
    foreach my $pos (sort {$a <=> $b} keys %{$seq_split{$id}}) {
        my $seq = $seq_split{$id}{$pos};
        while ($seq =~ m/(($repeatunit){$minRepeatNum,})/g) {
            my $length = length($1);
            my $end = pos($seq);
            $end = $end + $pos;
            my $start = $end - $length + 1;
            print "$id\t$seq_length{$id}\t$start\t$end\t$length\t$repeatunit\n";
        }
        while ($seq =~ m/(($repeatunit_reverse){$minRepeatNum,})/g) {
            my $length = length($1);
            my $end = pos($seq);
            $end = $end + $pos;
            my $start = $end - $length + 1;
            print "$id\t$seq_length{$id}\t$start\t$end\t$length\t$repeatunit_reverse\n";
        }
    }
}