File Coverage

blib/lib/BioX/Map.pm
Criterion Covered Total %
statement 91 117 77.7
branch 31 78 39.7
condition 4 12 33.3
subroutine 15 17 88.2
pod 4 4 100.0
total 145 228 63.6


line stmt bran cond sub pod time code
1             package BioX::Map;
2 3     3   80829 use Modern::Perl;
  3         4  
  3         14  
3 3     3   1107 use IO::All;
  3         14174  
  3         16  
4 3     3   1485 use Moo;
  3         23652  
  3         14  
5 3     3   3012 use Carp qw/confess/;
  3         2  
  3         111  
6 3     3   1515 use Types::Standard qw/Str Int Enum Bool/;
  3         135298  
  3         21  
7 3     3   3228 use File::Which;
  3         1863  
  3         119  
8 3     3   14 use Cwd;
  3         4  
  3         125  
9 3     3   2327 use IPC::Run qw/run timeout/;
  3         72329  
  3         123  
10 3     3   1522 use Parallel::ForkManager;
  3         27104  
  3         27  
11 3     3   986 use File::ShareDir ":ALL";
  3         8726  
  3         4222  
12              
13             our $VERSION = '0.0.11'; # 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 24187 my $self = shift;
114 3         74 my ($tool, $genome) = ($self->tool, $self->genome);
115 3         505 my @soap_suffix = qw/amb ann bwt fmv hot lkt pac rev.bwt rev.fmv rev.lkt rev.pac/;
116 3         10 my @bwa_suffix = qw/amb ann bwt pac sa/;
117 3         7 my $flag = 1;
118 3 50       19 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       312 $flag = 0 unless (-e "$genome.bwa.$suffix");
125             }
126             }
127 3         48 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         8 my ($soap, $bwa, $soap_index) = ($self->soap, $self->bwa, $self->soap_index);
135 1 50       121 confess "$genome is not exist" unless -e $genome;
136 1         3 my $genome_dir = io($genome)->filepath;
137 1         143 my $genome_name = io($genome)->filename;
138 1         119 chdir("$genome_dir");
139 1 50       27 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       3 if (@cmd) {
143 1         1 my ($in, $out, $err);
144 1         95 say join(" ", @cmd);
145 1 50       8 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
146 1         984856 chdir($ENV{'PWD'});
147 1 50       17 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     18 $infile ||= $self->infile;
155 1   33     34 $outfile ||= $self->outfile;
156 1         358 say "infile:$infile. outfile:$outfile";
157 1         40 my ($tool, $genome, $mismatch) = ($self->tool, $self->genome, $self->mismatch);
158 1         954 my ($soap, $bwa, $process_tool) = ($self->soap, $self->bwa, $self->process_tool);
159 1 50 33     61 $self->create_index if ($self->exist_index == 0 || $self->force_index);
160 1 50       1183 my $genome_index = $tool eq 'soap' ? "$genome.index"
    50          
161             : $tool eq 'bwa' ? "$genome.bwa"
162             : '';
163 1         2 my ($in, $out, $err, @cmd);
164 1 50       12 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         17 @cmd = ($bwa, "aln", "-n", $mismatch, "-t", $process_tool, "-f", "$outfile.sai", $genome_index, $infile);
171 1         177 say join(" ", @cmd);
172 1 50       15 run \@cmd, \$in, \$out, \$err or confess "cat $?: $err";
173             #return $err ? 0 : 1;
174 1         49410 @cmd = ($bwa, "samse", "-f", "$outfile", $genome_index, "$outfile.sai", "$infile");
175 1         32 say join(" ", @cmd);
176 1 50       7 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 13 my $self = shift;
184 1         23 my ($infile, $indir, $outfile, $outdir) = ($self->infile, $self->indir, $self->outfile, $self->outdir);
185 1         2165 my ($genome, $tool, $process_sample) = ($self->genome, $self->tool, $self->process_sample);
186 1 50       21 if ($indir) {
    50          
187 0     0   0 my @fqs = io($indir)->filter(sub {$_->filename =~/fastq|fq$/})->all_files;
  0         0  
188 0 0       0 return 0 unless (@fqs);
189 0 0       0 io($outdir)->mkpath unless -e $outdir;
190 0         0 my $pm = Parallel::ForkManager->new($process_sample);
191             DATA_LOOP:
192 0         0 for my $fq (@fqs) {
193 0 0       0 my $pid = $pm->start and next DATA_LOOP;
194 0         0 my $fq_name = $fq->filename;
195 0         0 $self->_map_one($fq, io->catfile($outdir, "$fq_name.$tool")->pathname);
196 0         0 $pm->finish;
197             }
198 0         0 $pm->wait_all_children;
199             } elsif ($infile) {
200 1 50       43 confess "$infile is not exist" unless -e $infile;
201 1         9 $self->_map_one;
202             }
203             }
204              
205              
206             sub statis_result {
207 1     1 1 25130 my ($self, $align_result) = @_;
208 1         27 my ($tool, $outfile) = ($self->tool, $self->outfile);
209 1   33     34 $outfile = $align_result || $outfile;
210 1         9 $outfile = io($outfile);
211 1 50       228 confess "$outfile is not exist" unless $outfile->exists;
212 1         26 my @result = (0, 0, 0);
213 1 50       7 if ($tool eq "soap") {
    50          
214 0         0 while (defined (my $line = $outfile->getline)) {
215 0         0 my @cols = split /\t/, $line;
216 0 0       0 next unless $cols[3] == 1;
217 0 0       0 $result[0]++ if ($cols[9] == 0);
218 0 0       0 $result[1]++ if ($cols[9] =~/^[01]$/);
219 0 0       0 $result[2]++ if ($cols[9] =~/^[012]$/);
220             }
221             } elsif ($tool eq 'bwa') {
222 1         20 while (defined (my $line = $outfile->getline)) {
223 12         1065 my @cols = split /\t/, $line;
224 12 100       46 next if $line =~/^@/;
225 7 100       14 next if @cols == 11;
226 6 50       8 next unless $cols[11] eq 'XT:A:U';
227 6 50       11 $result[0]++ if ($cols[12] eq 'NM:i:0');
228 6 50       15 $result[1]++ if ($cols[12] =~/NM:i:[01]/);
229 6 50       22 $result[2]++ if ($cols[12] =~/NM:i:[012]/);
230             }
231             }
232 1         135 return \@result;
233             }
234              
235             1;
236              
237             __END__