利用primer3批量设计引物

1、Primer3的下载与安装

primer3官网上下载相应版本的程序,解压后安装,然后检测是否有安装错误。例如安装2.6.1版本:

wget https://github.com/primer3-org/primer3/archive/refs/tags/v2.6.1.tar.gz
tar xzvf primer3-2.6.1.tar.gz
cd primer3-2.6.1/src
make
make test

安装好之后只需要调用src文件夹中的primer3_core程序就可以了,可以拷贝到其它的地方使用。

primer3的各参数说明可以参考官方文档,中文的可以参考这篇博客

2、模板的准备

将模板序列单独放在一个文件,如果是fasta格式的可以命名为fasta格式的代码读取文件,如果是tsv格式的(第一列为序列id,第二列为模板序列),使用tsv格式对应的代码读取文件。然后用下面代码进行批量设计。如果对引物条件不敏感,可以在参数中加入这个参数PRIMER_PICK_ANYWAY=1“,如果想获得多对引物可以修改这个参数”PRIMER_NUM_RETURN=1“。其它参数也可以根据需要修改或者添加。

如果只是检测设计的引物是否满足条件,可以引入以下函数修改对应的参数。

#!/usr/bin/perl
use strict;
use warnings;
my $primer3_core = "./primer3_core";
my $Seq_file = "./input_file";
my $primer3out_file = "./primer3out.txt";
############Change the parameter if need #######
my $primer3input = <<SET;
PRIMER_TASK=generic
PRIMER_PICK_LEFT_PRIMER=1
PRIMER_PICK_INTERNAL_OLIGO=0
PRIMER_PICK_RIGHT_PRIMER=1
PRIMER_PRODUCT_SIZE_RANGE=75-100
PRIMER_EXPLAIN_FLAG=1
PRIMER_FIRST_BASE_INDEX=1
PRIMER_LIBERAL_BASE=1
SEQUENCE_FORCE_LEFT_END=41
PRIMER_NUM_RETURN=1
PRIMER_OPT_SIZE=20
PRIMER_MIN_SIZE=18
PRIMER_MAX_SIZE=25
PRIMER_MIN_GC=30.0
PRIMER_MAX_GC=70.0
PRIMER_MIN_TM=58.0
PRIMER_OPT_TM=60.0
PRIMER_MAX_TM=62.0
=
SET
open(F, $Seq_file) or die "Can not open the flankingSeq file $!\n";
open(POUT, ">$primer3out_file");
my $print_out_head = join("\t", ("primer_id", "Foward", "Reverse"));
print POUT $print_out_head."\n";
my %id2seq;
my $id="";
my $seq="";
############if the input file is the fasta format##################
while(<F>){
	if(/^>(\S+)/){
		if($id){
			$id2seq{$id}=$seq;
			$seq="";
		}
		$id=$1;
	}else{
		s/\s+$//;
		$seq.=$_;
	}
	if(eof){
		$id2seq{$id}=$seq;
	}
}
############if the input file is the tsv format, use this code################
#while(<F>){
#	s/\s+$//;
#	($id, $seq)=split/\t/;
#	$id2seq{$id}=$seq;
#}		
		
foreach my $primer_id(keys %id2seq){
	my (@primer_left, @primer_right)=&primerPick($primer_id, $id2seq{$primer_id});
	my $i=0;
	while($i<=$#primer_left){
		print POUT $primer_id."\t".$primer_left[$i]."\t". $primer_right[$i]."\n" if($primer_left[$i] and $primer_right[$i]);
	}
}
	
close(POUT);
system("rm ./primer3input.txt");
sub primerPick{
	my ($snp_id, $template)=@_;
	my $attachmentSet = <<ASET;
SEQUENCE_ID=$snp_id
SEQUENCE_TEMPLATE=$template
ASET
	my $primer3set=$attachmentSet.$primer3input;
	open(OUT, ">./primer3input.txt");
	print OUT $primer3set;
	close(OUT);	
	
	my $primer3output = `$primer3_core --default_version=2 --io_version=4 --strict_tags  <./primer3input.txt `;
	my @primer_left="";
	if($primer3output=~/PRIMER_LEFT_(\d+)_SEQUENCE=(\w+)/g){
		$primer_left[$1]=$2;
	}
	my @primer_right="";
	if($primer3output=~/PRIMER_RIGHT_(\d+)_SEQUENCE=(\w+)/g){
		$primer_right[$1]=$2;
	}
	
	return @primer_left,@primer_right;
}
sub checkPrimer{
	my ($primer_id, $primer_left, $primer_right, $template)=@_;
	my $primer3set=$primer3input;
	$primer3set=~s/PRIMER_TASK=generic/PRIMER_TASK=check_primers/;
	$primer3set=~s/PRIMER_PICK_LEFT_PRIMER=1/PRIMER_PICK_LEFT_PRIMER=0/;
	$primer3set=~s/PRIMER_PICK_RIGHT_PRIMER=1/PRIMER_PICK_RIGHT_PRIMER=0/;
	my $attachmentSet = <<ASET;
SEQUENCE_ID=$primer_id
SEQUENCE_TEMPLATE=$template
SEQUENCE_PRIMER=$primer_left
SEQUENCE_PRIMER_REVCOMP=$primer_right
ASET
	$primer3set = $attachmentSet.$primer3set;
	open(OUT, ">./primer3input.txt");
	print OUT $primer3set;
	close(OUT);
	my $primer3out = `$primer3_core --default_version=2 --io_version=4 --strict_tags  <./primer3input.txt `;
	if($primer3out=~/PRIMER_PAIR_EXPLAIN=considered 1, ok 1/){
		return 1;
	}else{
		return 0;
	}
}