File Coverage

blib/lib/App/Fasops/Command/check.pm
Criterion Covered Total %
statement 38 89 42.7
branch 4 28 14.2
condition 0 6 0.0
subroutine 11 13 84.6
pod 6 7 85.7
total 59 143 41.2


line stmt bran cond sub pod time code
1             package App::Fasops::Command::check;
2 21     21   19002 use strict;
  21         61  
  21         712  
3 21     21   111 use warnings;
  21         41  
  21         669  
4 21     21   111 use autodie;
  21         42  
  21         167  
5              
6 21     21   107312 use App::Fasops -command;
  21         60  
  21         274  
7 21     21   8879 use App::RL::Common;
  21         46  
  21         614  
8 21     21   126 use App::Fasops::Common;
  21         41  
  21         23917  
9              
10              
11             sub abstract {
12 2     2 1 53 return 'check genome locations in (blocked) fasta headers';
13             }
14              
15             sub opt_spec {
16             return (
17 4     4 1 33 [ "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 38177 return "fasops check [options] ";
25             }
26              
27             sub description {
28 1     1 1 666 my $desc;
29 1         4 $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         3 return $desc;
39             }
40              
41             sub validate_args {
42 3     3 1 1979 my ( $self, $opt, $args ) = @_;
43              
44 3 100       4 if ( @{$args} != 2 ) {
  3         12  
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         22 $self->usage_error($message);
49             }
50 1         4 for ( @{$args} ) {
  1         3  
51 1 50       4 next if lc $_ eq "stdin";
52 1 50       7 if ( !Path::Tiny::path($_)->is_file ) {
53 1         112 $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 App::Fasops::Common::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             1;