FASTA形式の塩基配列(アミノ酸配列)ファイルをNEXUS形式やPHYLIP形式に変換したい、ということはよくあります。単一のファイルならClustalwやMacCladeを使用して変換できますが、多数のFASTAファイルを扱う場合(数百〜数千遺伝子を用いた系統解析など)、一括でファイル形式を変換するスクリプトがあれば便利です。
ここでは、FASTA形式 --> NEXUS形式、またはFASTA形式 --> PHYLIP形式へ変換するPerlスクリプトを公開します。アラインメント自体は行わないので、すでにアラインメントされたFASTA形式ファイルのみが対象になります。また、配列名は9文字まで、という制約があります。
(1) fasta_to_nex.pl
#!/usr/bin/perl
use strict;
use warnings;
my $fname = $ARGV[0];
my @lines = ();
my @seq_with_name = ();
my $ntax = 0;
my $nchar = 0;
my $seq_data = 0;
my $datatype = 'dna';
my %sequence;
open (FASTA, "$fname") || die "Cannot open file:$!";
while(<FASTA>) {
chomp;
push(@lines, $_);
}
close(FASTA);
foreach my $line (@lines) {
$ntax++ if($line =~ /\>/);
}
$sequence{"Name"} = shift(@lines);
$sequence{"Name"} =~ s/\>//;
while ($#lines > -1) {
my $data = shift(@lines);
if($data =~ /\>/) {
$nchar = length($sequence{"Sequence"});
while(length($sequence{"Name"}) < 10) {
$sequence{"Name"} .= " ";
}
$seq_data = $sequence{"Name"} . $sequence{"Sequence"};
push(@seq_with_name, $seq_data);
$sequence{"Sequence"} = "";
$sequence{"Name"} = $data;
$sequence{"Name"} =~ s/\>//;
} else {
$sequence{"Sequence"} .= $data;
}
}
while(length($sequence{"Name"}) < 10) {
$sequence{"Name"} .= " ";
}
$seq_data = $sequence{"Name"} . $sequence{"Sequence"};
push(@seq_with_name, $seq_data);
print '#NEXUS', "\n\n";
print '[', "\n", 'Data from:', "\n", $ARGV[0], "\n", ']', "\n\n\n";
print 'begin data;', "\n ", 'dimensions ntax=', $ntax, ' nchar=', $nchar, ';', "\n";
print ' format datatype=', $datatype, ' interleave=no gap=-;', "\n";
print ' matrix', "\n";
foreach(@seq_with_name) {
print $_, "\n";
}
print ' ;', "\n";
print 'end;', "\n";
(2) fasta_to_phy.pl
#!/usr/bin/perl
use strict;
use warnings;
my $fname = $ARGV[0];
my @lines = ();
my @seq_with_name = ();
my $ntax = 0;
my $nchar = 0;
my $seq_data = 0;
my %sequence;
open (FASTA, "$fname") || die "Cannot open file:$!";
while(<FASTA>) {
chomp;
push(@lines, $_);
}
close(FASTA);
foreach my $line (@lines) {
$ntax++ if($line =~ /\>/);
}
$sequence{"Name"} = shift(@lines);
$sequence{"Name"} =~ s/\>//;
while ($#lines > -1) {
my $data = shift(@lines);
if($data =~ /\>/) {
$nchar = length($sequence{"Sequence"});
while(length($sequence{"Name"}) < 10) {
$sequence{"Name"} .= " ";
}
$seq_data = $sequence{"Name"} . $sequence{"Sequence"};
push(@seq_with_name, $seq_data);
$sequence{"Sequence"} = "";
$sequence{"Name"} = $data;
$sequence{"Name"} =~ s/\>//;
} else {
$sequence{"Sequence"} .= $data;
}
}
while(length($sequence{"Name"}) < 10) {
$sequence{"Name"} .= " ";
}
$seq_data = $sequence{"Name"} . $sequence{"Sequence"};
push(@seq_with_name, $seq_data);
print $ntax, " ", $nchar, "\n";
foreach(@seq_with_name) {
print $_, "\n";
}
複数ファイルを一括で変換する場合は、以下のshell scriptを使用して下さい。カレントディレクトリにあるすべての".aln"拡張子を持つFASTA形式のファイルを変換します(注意:clustal formatには対応していません! 拡張子.alnでも)
(1) FtoN.sh
mkdir nex_files
for fname in *.aln; do
fname=`echo "$fname" | sed -E 's/\.aln//g'`
./fasta_to_nex.pl $fname.aln > $fname.nex
mv $fname.nex nex_files
done
(2) FtoP.sh
mkdir phy_files
for fname in *.aln; do
fname=`echo "$fname" | sed -E 's/\.aln//g'`
./fasta_to_phy.pl $fname.aln > $fname.phy
mv $fname.phy phy_files
done
ファイル形式の変換、一般的に、FASTAから別の形式への変換を行うことは多いですが、逆のパターンは少ない気がします。