annotate pyPRADA_1.2/tools/samtools-0.1.16/misc/sam2vcf.pl @ 0:acc2ca1a3ba4

Uploaded
author siyuan
date Thu, 20 Feb 2014 00:44:58 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
1 #!/usr/bin/perl -w
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
2 #
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
3 # VCF specs: http://www.1000genomes.org/wiki/doku.php?id=1000_genomes:analysis:vcf3.3
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
4 #
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
5 # Contact: pd3@sanger
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
6 # Version: 2010-04-23
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
7
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
8 use strict;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
9 use warnings;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
10 use Carp;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
11
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
12 my $opts = parse_params();
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
13 do_pileup_to_vcf($opts);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
14
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
15 exit;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
16
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
17 #---------------
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
18
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
19 sub error
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
20 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
21 my (@msg) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
22 if ( scalar @msg ) { croak(@msg); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
23 die
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
24 "Usage: sam2vcf.pl [OPTIONS] < in.pileup > out.vcf\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
25 "Options:\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
26 " -h, -?, --help This help message.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
27 " -i, --indels-only Ignore SNPs.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
28 " -r, --refseq <file.fa> The reference sequence, required when indels are present.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
29 " -R, --keep-ref Print reference alleles as well.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
30 " -s, --snps-only Ignore indels.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
31 " -t, --column-title <string> The column title.\n",
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
32 "\n";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
33 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
34
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
35
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
36 sub parse_params
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
37 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
38 my %opts = ();
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
39
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
40 $opts{fh_in} = *STDIN;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
41 $opts{fh_out} = *STDOUT;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
42
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
43 while (my $arg=shift(@ARGV))
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
44 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
45 if ( $arg eq '-R' || $arg eq '--keep-ref' ) { $opts{keep_ref}=1; next; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
46 if ( $arg eq '-r' || $arg eq '--refseq' ) { $opts{refseq}=shift(@ARGV); next; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
47 if ( $arg eq '-t' || $arg eq '--column-title' ) { $opts{title}=shift(@ARGV); next; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
48 if ( $arg eq '-s' || $arg eq '--snps-only' ) { $opts{snps_only}=1; next; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
49 if ( $arg eq '-i' || $arg eq '--indels-only' ) { $opts{indels_only}=1; next; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
50 if ( $arg eq '-?' || $arg eq '-h' || $arg eq '--help' ) { error(); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
51
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
52 error("Unknown parameter \"$arg\". Run -h for help.\n");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
53 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
54 return \%opts;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
55 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
56
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
57 sub iupac_to_gtype
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
58 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
59 my ($ref,$base) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
60 my %iupac = (
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
61 'K' => ['G','T'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
62 'M' => ['A','C'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
63 'S' => ['C','G'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
64 'R' => ['A','G'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
65 'W' => ['A','T'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
66 'Y' => ['C','T'],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
67 );
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
68 if ( !exists($iupac{$base}) )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
69 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
70 if ( $base ne 'A' && $base ne 'C' && $base ne 'G' && $base ne 'T' ) { error("FIXME: what is this [$base]?\n"); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
71 if ( $ref eq $base ) { return ('.','0/0'); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
72 return ($base,'1/1');
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
73 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
74 my $gt = $iupac{$base};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
75 if ( $$gt[0] eq $ref ) { return ($$gt[1],'0/1'); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
76 elsif ( $$gt[1] eq $ref ) { return ($$gt[0],'0/1'); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
77 return ("$$gt[0],$$gt[1]",'1/2');
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
78 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
79
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
80
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
81 sub parse_indel
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
82 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
83 my ($cons) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
84 if ( $cons=~/^-/ )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
85 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
86 my $len = length($');
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
87 return "D$len";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
88 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
89 elsif ( $cons=~/^\+/ ) { return "I$'"; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
90 elsif ( $cons eq '*' ) { return undef; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
91 error("FIXME: could not parse [$cons]\n");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
92 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
93
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
94
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
95 # An example of the pileup format:
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
96 # 1 3000011 C C 32 0 98 1 ^~, A
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
97 # 1 3002155 * +T/+T 53 119 52 5 +T * 4 1 0
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
98 # 1 3003094 * -TT/-TT 31 164 60 11 -TT * 5 6 0
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
99 # 1 3073986 * */-AAAAAAAAAAAAAA 3 3 45 9 * -AAAAAAAAAAAAAA 7 2 0
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
100 #
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
101 sub do_pileup_to_vcf
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
102 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
103 my ($opts) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
104
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
105 my $fh_in = $$opts{fh_in};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
106 my $fh_out = $$opts{fh_out};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
107 my ($prev_chr,$prev_pos,$prev_ref);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
108 my $refseq;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
109 my $ignore_indels = $$opts{snps_only} ? 1 : 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
110 my $ignore_snps = $$opts{indels_only} ? 1 : 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
111 my $keep_ref = $$opts{keep_ref} ? 1 : 0;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
112 my $title = exists($$opts{title}) ? $$opts{title} : 'data';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
113
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
114 print $fh_out
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
115 qq[##fileformat=VCFv3.3\n],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
116 qq[##INFO=DP,1,Integer,"Total Depth"\n],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
117 qq[##FORMAT=GT,1,String,"Genotype"\n],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
118 qq[##FORMAT=GQ,1,Integer,"Genotype Quality"\n],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
119 qq[##FORMAT=DP,1,Integer,"Read Depth"\n],
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
120 qq[#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT\t$title\n]
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
121 ;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
122
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
123 while (my $line=<$fh_in>)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
124 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
125 chomp($line);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
126 my (@items) = split(/\t/,$line);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
127 if ( scalar @items<8 )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
128 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
129 error("\nToo few columns, does not look like output of 'samtools pileup -c': $line\n");
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
130 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
131 my ($chr,$pos,$ref,$cons,$cons_qual,$snp_qual,$rms_qual,$depth,$a1,$a2) = @items;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
132 $ref = uc($ref);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
133 $cons = uc($cons);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
134
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
135 my ($alt,$gt);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
136 if ( $ref eq '*' )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
137 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
138 # An indel is involved.
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
139 if ( $ignore_indels )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
140 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
141 $prev_ref = $ref;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
142 $prev_pos = $pos;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
143 $prev_chr = $chr;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
144 next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
145 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
146
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
147 if (!defined $prev_chr || $chr ne $prev_chr || $pos ne $prev_pos)
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
148 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
149 if ( !$$opts{refseq} ) { error("Cannot do indels without the reference.\n"); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
150 if ( !$refseq ) { $refseq = Fasta->new(file=>$$opts{refseq}); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
151 $ref = $refseq->get_base($chr,$pos);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
152 $ref = uc($ref);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
153 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
154 else { $ref = $prev_ref; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
155
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
156 # One of the alleles can be a reference and it can come in arbitrary order. In some
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
157 # cases */* can be encountered. In such a case, look in the additional columns.
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
158 my ($al1,$al2) = split(m{/},$cons);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
159 if ( $al1 eq $al2 && $al1 eq '*' ) { $al1=$a1; $al2=$a2; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
160 my $alt1 = parse_indel($al1);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
161 my $alt2 = parse_indel($al2);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
162 if ( !$alt1 && !$alt2 ) { error("FIXME: could not parse indel:\n", $line); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
163 if ( !$alt1 )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
164 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
165 $alt=$alt2;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
166 $gt='0/1';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
167 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
168 elsif ( !$alt2 )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
169 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
170 $alt=$alt1;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
171 $gt='0/1';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
172 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
173 elsif ( $alt1 eq $alt2 )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
174 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
175 $alt="$alt1";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
176 $gt='1/1';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
177 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
178 else
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
179 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
180 $alt="$alt1,$alt2";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
181 $gt='1/2';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
182 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
183 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
184 else
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
185 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
186 if ( $ignore_snps || (!$keep_ref && $ref eq $cons) )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
187 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
188 $prev_ref = $ref;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
189 $prev_pos = $pos;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
190 $prev_chr = $chr;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
191 next;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
192 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
193
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
194 # SNP
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
195 ($alt,$gt) = iupac_to_gtype($ref,$cons);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
196 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
197
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
198 print $fh_out "$chr\t$pos\t.\t$ref\t$alt\t$snp_qual\t0\tDP=$depth\tGT:GQ:DP\t$gt:$cons_qual:$depth\n";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
199
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
200 $prev_ref = $ref;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
201 $prev_pos = $pos;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
202 $prev_chr = $chr;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
203 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
204 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
205
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
206
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
207 #------------- Fasta --------------------
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
208 #
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
209 # Uses samtools to get a requested base from a fasta file. For efficiency, preloads
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
210 # a chunk to memory. The size of the cached sequence can be controlled by the 'size'
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
211 # parameter.
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
212 #
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
213 package Fasta;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
214
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
215 use strict;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
216 use warnings;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
217 use Carp;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
218
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
219 sub Fasta::new
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
220 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
221 my ($class,@args) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
222 my $self = {@args};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
223 bless $self, ref($class) || $class;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
224 if ( !$$self{file} ) { $self->throw(qq[Missing the parameter "file"\n]); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
225 $$self{chr} = undef;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
226 $$self{from} = undef;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
227 $$self{to} = undef;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
228 if ( !$$self{size} ) { $$self{size}=10_000_000; }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
229 bless $self, ref($class) || $class;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
230 return $self;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
231 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
232
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
233 sub read_chunk
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
234 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
235 my ($self,$chr,$pos) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
236 my $to = $pos + $$self{size};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
237 my $cmd = "samtools faidx $$self{file} $chr:$pos-$to";
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
238 my @out = `$cmd`;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
239 if ( $? ) { $self->throw("$cmd: $!"); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
240 my $line = shift(@out);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
241 if ( !($line=~/^>$chr:(\d+)-(\d+)/) ) { $self->throw("Could not parse: $line"); }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
242 $$self{chr} = $chr;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
243 $$self{from} = $1;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
244 $$self{to} = $2;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
245 my $chunk = '';
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
246 while ($line=shift(@out))
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
247 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
248 chomp($line);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
249 $chunk .= $line;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
250 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
251 $$self{chunk} = $chunk;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
252 return;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
253 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
254
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
255 sub get_base
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
256 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
257 my ($self,$chr,$pos) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
258 if ( !$$self{chr} || $chr ne $$self{chr} || $pos<$$self{from} || $pos>$$self{to} )
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
259 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
260 $self->read_chunk($chr,$pos);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
261 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
262 my $idx = $pos - $$self{from};
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
263 return substr($$self{chunk},$idx,1);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
264 }
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
265
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
266 sub throw
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
267 {
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
268 my ($self,@msg) = @_;
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
269 croak(@msg);
acc2ca1a3ba4 Uploaded
siyuan
parents:
diff changeset
270 }