File Coverage

blib/lib/BioX/Map.pm
Criterion Covered Total %
statement 92 118 77.9
branch 32 80 40.0
condition 4 12 33.3
subroutine 15 17 88.2
pod 4 4 100.0
total 147 231 63.6


line stmt bran cond sub pod time code
1             package BioX::Map;
2 3     3   93816 use Modern::Perl;
  3         5  
  3         14  
3 3     3   1162 use IO::All;
  3         14462  
  3         24  
4 3     3   1495 use Moo;
  3         25712  
  3         19  
5 3     3   3590 use Carp qw/confess/;
  3         5  
  3         143  
6 3     3   2019 use Types::Standard qw/Str Int Enum Bool/;
  3         144722  
  3         30  
7 3     3   4160 use File::Which;
  3         2324  
  3         155  
8 3     3   15 use Cwd;
  3         4  
  3         154  
9 3     3   2821 use IPC::Run qw/run timeout/;
  3         92824  
  3         172  
10 3     3   1968 use Parallel::ForkManager;
  3         28821  
  3         36  
11 3     3   967 use File::ShareDir ":ALL";
  3         8863  
  3         5577  
12              
13             our $VERSION = '0.0.10'; # VERSION
14             # ABSTRACT: map read to genome with bwa and soap
15              
16              
17              
18             has infile => (
19             is => "ro",
20             isa => Str,
21             default => '',
22             );
23              
24              
25             has indir => (
26             is => 'ro',
27             isa => Str,
28             );
29              
30              
31             has outfile => (
32             is => 'lazy',
33             isa => Str,
34             );
35              
36              
37             has outdir => (
38             is => 'lazy',
39             isa => Str,
40             default => "./",
41             );
42              
43              
44             has force_index => (
45             is => 'lazy',
46             isa => Bool,
47             default => 0,
48             );
49              
50              
51             has mismatch => (
52             is => 'lazy',
53             isa => Int,
54             default => 2,
55             );
56              
57              
58             has genome => (
59             is => 'ro',
60             isa => Str,
61             );
62              
63              
64             has tool => (
65             is => 'rw',
66             isa => Enum['bwa', 'soap'],
67             default => "soap",
68             );
69              
70              
71             has bwa => (
72             is => "lazy",
73             isa => Str,
74             default => sub { dist_file('BioX-Map', 'exe/bwa') },
75             );
76              
77              
78             has soap => (
79             is => "lazy",
80             isa => Str,
81             default => sub { dist_file('BioX-Map', 'exe/soap') },
82             );
83              
84              
85             has soap_index => (
86             is => "lazy",
87             isa => Str,
88             default => sub { dist_file('BioX-Map', 'exe/2bwt-builder') },
89             );
90              
91              
92             has process_tool => (
93             is => 'ro',
94             isa => Int,
95             default => 1,
96             );
97              
98              
99             has process_sample => (
100             is => 'ro',
101             isa => Int,
102             default => 1,
103             );
104              
105             sub _build_outfile {
106 0     0   0 my $self = shift;
107 0         0 my $infile = io($self->infile);
108 0 0       0 return $infile->exists ? io->catfile($ENV{PWD}, $infile->filename . "." . $_[0]->tool) : '';
109             }
110              
111              
112             sub exist_index {
113 3     3 1 25399 my $self = shift;
114 3         42 my ($tool, $genome) = ($self->tool, $self->genome);
115 3         486 my @soap_suffix = qw/amb ann bwt fmv hot lkt pac rev.bwt rev.fmv rev.lkt rev.pac/;
116 3         8 my @bwa_suffix = qw/amb ann bwt pac sa/;
117 3         5 my $flag = 1;
118 3 50       14 if ($tool eq 'soap') {
    50          
119 0         0 for my $suffix (@soap_suffix) {
120 0 0       0 $flag = 0 unless (-e "$genome.index.$suffix");
121             }
122             } elsif ($tool eq 'bwa') {
123 3         8 for my $suffix (@bwa_suffix) {
124 15 100       266 $flag = 0 unless (-e "$genome.bwa.$suffix");
125             }
126             }
127 3         27 return $flag;
128             }
129              
130              
131             sub create_index {
132 1     1 1 5 my $self = shift;
133 1         21 my ($tool, $genome) = ($self->tool, $self->genome);
134 1         9 my ($soap, $bwa, $soap_index) = ($self->soap, $self->bwa, $self->soap_index);
135 1 50       124 confess "$genome is not exist" unless -e $genome;
136 1         6 my $genome_dir = io($genome)->filepath;
137 1         227 my $genome_name = io($genome)->filename;
138 1         163 chdir("$genome_dir");
139 1 50       45 my @cmd = $tool eq 'soap' ? ($soap_index, $genome_name)
    50          
140             : $tool eq 'bwa' ? ($bwa, 'index', '-a', 'bwtsw', '-p', "$genome_name.bwa", "$genome_name")
141             : ();
142 1 50       5 if (@cmd) {
143 1         1 my ($in, $out, $err);
144 1         173 say join(" ", @cmd);
145 1 50       8 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
146 1         36204838 chdir($ENV{'PWD'});
147 1 50       11 return $self->exist_index ? 1 : 0;
148             }
149             }
150              
151              
152             sub _map_one {
153 1     1   3 my ($self, $infile, $outfile) = @_;
154 1   33     8 $infile ||= $self->infile;
155 1   33     18 $outfile ||= $self->outfile;
156 1         209 say "infile:$infile. outfile:$outfile";
157 1         25 my ($tool, $genome, $mismatch) = ($self->tool, $self->genome, $self->mismatch);
158 1         546 my ($soap, $bwa, $process_tool) = ($self->soap, $self->bwa, $self->process_tool);
159 1 50 33     28 $self->create_index if ($self->exist_index == 0 || $self->force_index);
160 1 50       494 my $genome_index = $tool eq 'soap' ? "$genome.index"
    50          
161             : $tool eq 'bwa' ? "$genome.bwa"
162             : '';
163 1         3 my ($in, $out, $err, @cmd);
164 1 50       5 if ($tool eq 'soap') {
    50          
165 0         0 @cmd = ($soap, "-a", $infile, "-p", $process_tool, "-D", $genome_index, "-o", "$outfile");
166 0         0 say join(" ", @cmd);
167 0 0       0 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
168 0 0       0 return $err ? 0 : 1;
169             } elsif ($tool eq 'bwa') {
170 1         5 @cmd = ($bwa, "aln", "-n", $mismatch, "-t", $process_tool, "-f", "$outfile.sai", $genome_index, $infile);
171 1         96 say join(" ", @cmd);
172 1 50       12 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
173             #return $err ? 0 : 1;
174 1         18782 @cmd = ($bwa, "samse", "-f", "$outfile", $genome_index, "$outfile.sai", "$infile");
175 1         211 say join(" ", @cmd);
176 1 50       12 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
177             #return $err ? 0 : 1;
178             }
179             }
180              
181              
182             sub map {
183 1     1 1 7 my $self = shift;
184 1         13 my ($infile, $indir, $outfile, $outdir) = ($self->infile, $self->indir, $self->outfile, $self->outdir);
185 1         1204 my ($genome, $tool, $process_sample) = ($self->genome, $self->tool, $self->process_sample);
186 1 50       23 confess "$genome is not exist" unless -e $genome;
187 1 50       9 if ($indir) {
    50          
188 0     0   0 my @fqs = io($indir)->filter(sub {$_->filename =~/fastq|fq$/})->all_files;
  0         0  
189 0 0       0 return 0 unless (@fqs);
190 0 0       0 io($outdir)->mkpath unless -e $outdir;
191 0         0 my $pm = Parallel::ForkManager->new($process_sample);
192             DATA_LOOP:
193 0         0 for my $fq (@fqs) {
194 0 0       0 my $pid = $pm->start and next DATA_LOOP;
195 0         0 my $fq_name = $fq->filename;
196 0         0 $self->_map_one($fq, io->catfile($outdir, "$fq_name.$tool")->pathname);
197 0         0 $pm->finish;
198             }
199 0         0 $pm->wait_all_children;
200             } elsif ($infile) {
201 1 50       19 confess "$infile is not exist" unless -e $infile;
202 1         4 $self->_map_one;
203             }
204             }
205              
206              
207             sub statis_result {
208 1     1 1 32678 my ($self, $align_result) = @_;
209 1         32 my ($tool, $outfile) = ($self->tool, $self->outfile);
210 1   33     37 $outfile = $align_result || $outfile;
211 1         9 $outfile = io($outfile);
212 1 50       256 confess "$outfile is not exist" unless $outfile->exists;
213 1         29 my @result = (0, 0, 0);
214 1 50       11 if ($tool eq "soap") {
    50          
215 0         0 while (defined (my $line = $outfile->getline)) {
216 0         0 my @cols = split /\t/, $line;
217 0 0       0 next unless $cols[3] == 1;
218 0 0       0 $result[0]++ if ($cols[9] == 0);
219 0 0       0 $result[1]++ if ($cols[9] =~/^[01]$/);
220 0 0       0 $result[2]++ if ($cols[9] =~/^[012]$/);
221             }
222             } elsif ($tool eq 'bwa') {
223 1         31 while (defined (my $line = $outfile->getline)) {
224 12         1208 my @cols = split /\t/, $line;
225 12 100       37 next if $line =~/^@/;
226 7 100       15 next if @cols == 11;
227 6 50       11 next unless $cols[11] eq 'XT:A:U';
228 6 50       14 $result[0]++ if ($cols[12] eq 'NM:i:0');
229 6 50       20 $result[1]++ if ($cols[12] =~/NM:i:[01]/);
230 6 50       32 $result[2]++ if ($cols[12] =~/NM:i:[012]/);
231             }
232             }
233 1         136 return \@result;
234             }
235              
236             1;
237              
238             __END__