File Coverage

blib/lib/App/Fasops/Command/check.pm
Criterion Covered Total %
statement 38 100 38.0
branch 4 30 13.3
condition 0 6 0.0
subroutine 11 14 78.5
pod 6 8 75.0
total 59 158 37.3


line stmt bran cond sub pod time code
1             package App::Fasops::Command::check;
2 20     20   17749 use strict;
  20         56  
  20         674  
3 20     20   109 use warnings;
  20         41  
  20         585  
4 20     20   109 use autodie;
  20         50  
  20         147  
5              
6 20     20   106446 use App::Fasops -command;
  20         45  
  20         268  
7 20     20   8377 use App::RL::Common;
  20         56  
  20         513  
8 20     20   109 use App::Fasops::Common;
  20         42  
  20         26853  
9              
10              
11             sub abstract {
12 2     2 1 52 return 'check genome locations in (blocked) fasta headers';
13             }
14              
15             sub opt_spec {
16             return (
17 4     4 1 25 [ "outfile|o=s", "Output filename. [stdout] for screen." ],
18             [ "name|n=s", "Which species to be checked, omit this will check all sequences" ],
19             { show_defaults => 1, }
20             );
21             }
22              
23             sub usage_desc {
24 4     4 1 44002 return "fasops check [options] ";
25             }
26              
27             sub description {
28 1     1 1 817 my $desc;
29 1         6 $desc .= ucfirst(abstract) . ".\n";
30 1         3 $desc .= <<'MARKDOWN';
31              
32             * are paths to axt files, .axt.gz is supported
33             * infile == stdin means reading from STDIN
34             * is one multi fasta file contains genome sequences
35              
36             MARKDOWN
37              
38 1         5 return $desc;
39             }
40              
41             sub validate_args {
42 3     3 1 2433 my ( $self, $opt, $args ) = @_;
43              
44 3 100       6 if ( @{$args} != 2 ) {
  3         11  
45 2         4 my $message = "This command need two input files.\n\tIt found";
46 2         3 $message .= sprintf " [%s]", $_ for @{$args};
  2         10  
47 2         4 $message .= ".\n";
48 2         13 $self->usage_error($message);
49             }
50 1         3 for ( @{$args} ) {
  1         3  
51 1 50       5 next if lc $_ eq "stdin";
52 1 50       8 if ( !Path::Tiny::path($_)->is_file ) {
53 1         113 $self->usage_error("The input file [$_] doesn't exist.");
54             }
55             }
56              
57 0 0         if ( !exists $opt->{outfile} ) {
58 0           $opt->{outfile} = Path::Tiny::path( $args->[0] )->absolute . ".check.txt";
59             }
60              
61             # samtools should be in $PATH
62 0 0         if ( !IPC::Cmd::can_run("samtools") ) {
63 0           $self->usage_error("Can't find [samtools].");
64             }
65             }
66              
67             sub execute {
68 0     0 1   my ( $self, $opt, $args ) = @_;
69              
70 0           my $in_fh;
71 0 0         if ( lc $args->[0] eq "stdin" ) {
72 0           $in_fh = *STDIN{IO};
73             }
74             else {
75 0           $in_fh = IO::Zlib->new( $args->[0], "rb" );
76             }
77              
78 0           my $out_fh;
79 0 0         if ( lc( $opt->{outfile} ) eq "stdout" ) {
80 0           $out_fh = *STDOUT{IO};
81             }
82             else {
83 0           open $out_fh, ">", $opt->{outfile};
84             }
85              
86             {
87 0           my $header;
  0            
88 0           my $content = '';
89 0           while ( my $line = $in_fh->getline ) {
90 0           chomp $line;
91              
92 0 0         if ( $line =~ /^\>[\w:-]+/ ) {
    0          
93              
94             # the first sequence is ready
95 0 0         if ( defined $header ) {
96 0           check_seq( $header, $content, $args->[1], $out_fh, $opt->{name}, );
97             }
98              
99             # prepare to accept next sequence
100 0           $line =~ s/^\>//;
101 0           $header = $line;
102              
103             # clean previous sequence
104 0           $content = '';
105             }
106             elsif ( $line =~ /^[\w-]+/ ) {
107 0           $line =~ s/[^\w]//g; # Delete '-'s
108 0           $line = uc $line;
109 0           $content .= $line;
110             }
111             else { # Blank line, do nothing
112             }
113             }
114              
115             # for last sequece
116 0           check_seq( $header, $content, $args->[1], $out_fh, $opt->{name}, );
117             }
118              
119 0           close $out_fh;
120 0           $in_fh->close;
121             }
122              
123             sub check_seq {
124 0     0 0   my $header = shift;
125 0           my $seq = shift;
126 0           my $file_genome = shift;
127 0           my $out_fh = shift;
128 0           my $name = shift;
129              
130 0           my $info = App::RL::Common::decode_header($header);
131              
132 0 0 0       if ( $name and $name ne $info->{name} ) {
133 0           return;
134             }
135              
136 0 0         if ( $info->{strand} eq '-' ) {
137 0           $seq = App::Fasops::Common::revcom($seq);
138             }
139              
140 0           my $location;
141 0 0 0       if ( $info->{end} and $info->{start} < $info->{end} ) {
142 0           $location = sprintf "%s:%s-%s", $info->{chr}, $info->{start}, $info->{end};
143             }
144             else {
145 0           $location = sprintf "%s:%s", $info->{chr}, $info->{start};
146             }
147 0           my $seq_in_genome = uc get_seq_faidx( $file_genome, $location );
148              
149 0           my $status = "FAILED";
150 0 0         if ( $seq eq $seq_in_genome ) {
151 0           $status = "OK";
152             }
153              
154 0           printf {$out_fh} "%s\t%s\n", $header, $status;
  0            
155              
156 0           return;
157             }
158              
159             sub get_seq_faidx {
160 0     0 0   my $file_genome = shift;
161 0           my $location = shift; # I:1-100
162              
163 0           my $cmd = sprintf "samtools faidx %s %s", $file_genome, $location;
164 0           open my $fh_pipe, '-|', $cmd;
165              
166 0           my $seq;
167 0           while ( my $line = <$fh_pipe> ) {
168 0           chomp $line;
169 0 0         if ( $line =~ /^[\w-]+/ ) {
170 0           $seq .= $line;
171             }
172             }
173 0           close($fh_pipe);
174              
175 0           return $seq;
176             }
177              
178             1;