File Coverage

blib/lib/App/RL/Command/position.pm
Criterion Covered Total %
statement 83 89 93.2
branch 30 40 75.0
condition n/a
subroutine 11 11 100.0
pod 5 5 100.0
total 129 145 88.9


line stmt bran cond sub pod time code
1             package App::RL::Command::position;
2 14     14   8787 use strict;
  14         34  
  14         425  
3 14     14   83 use warnings;
  14         30  
  14         315  
4 14     14   62 use autodie;
  14         31  
  14         67  
5              
6 14     14   69084 use App::RL -command;
  14         36  
  14         440  
7 14     14   4405 use App::RL::Common;
  14         29  
  14         334  
8              
9 14     14   64 use constant abstract => 'compare runlists against positions';
  14         27  
  14         13070  
10              
11             sub opt_spec {
12             return (
13 7     7 1 54 [ "outfile|o=s", "Output filename. [stdout] for screen." ],
14             [ "op=s", "operations: overlap, non-overlap or superset", { default => "overlap" } ],
15             [ "remove|r", "Remove 'chr0' from chromosome names." ],
16             { show_defaults => 1, }
17             );
18             }
19              
20             sub usage_desc {
21 7     7 1 54083 return "runlist position [options] ";
22             }
23              
24             sub description {
25 1     1 1 839 my $desc;
26 1         3 $desc .= ucfirst(abstract) . ".\n";
27 1         3 $desc .= " " x 4 . "Genome positions:\n";
28 1         3 $desc .= " " x 4 . "I:1-100\tPreferred format;\n";
29 1         3 $desc .= " " x 4 . "I(+):90-150\tStrand will be ommitted;\n";
30 1         2 $desc .= " " x 4 . "S288c.I(-):190-200\tSpecies names will be omitted\.n";
31 1         3 return $desc;
32             }
33              
34             sub validate_args {
35 6     6 1 6107 my ( $self, $opt, $args ) = @_;
36              
37 6 100       13 if ( @{$args} < 2 ) {
  6         25  
38 2         5 my $message = "This command need two input files.\n\tIt found";
39 2         4 $message .= sprintf " [%s]", $_ for @{$args};
  2         11  
40 2         5 $message .= ".\n";
41 2         12 $self->usage_error($message);
42             }
43 4         8 for ( @{$args} ) {
  4         13  
44 7 50       243 next if lc $_ eq "stdin";
45 7 100       29 if ( !Path::Tiny::path($_)->is_file ) {
46 1         117 $self->usage_error("The input file [$_] doesn't exist.");
47             }
48             }
49              
50 3 100       129 if ( $opt->{op} =~ /^overlap/i ) {
    100          
    50          
51 1         3 $opt->{op} = 'overlap';
52             }
53             elsif ( $opt->{op} =~ /^non/i ) {
54 1         63 $opt->{op} = 'non-overlap';
55             }
56             elsif ( $opt->{op} =~ /^superset/i ) {
57 1         3 $opt->{op} = 'superset';
58             }
59             else {
60 0         0 Carp::confess "[@{[$opt->{op}]}] invalid\n";
  0         0  
61             }
62              
63 3 50       17 if ( !exists $opt->{outfile} ) {
64 0         0 $opt->{outfile} = Path::Tiny::path( $args->[0] )->absolute . "." . $opt->{op} . ".yml";
65             }
66             }
67              
68             sub execute {
69 3     3 1 20 my ( $self, $opt, $args ) = @_;
70              
71             #----------------------------#
72             # Loading
73             #----------------------------#
74 3         35 my $chrs = Set::Scalar->new;
75              
76             my $set_single
77 3         383 = App::RL::Common::runlist2set( YAML::Syck::LoadFile( $args->[0] ), $opt->{remove} );
78 3         50 $chrs->insert( keys %{$set_single} );
  3         57  
79              
80             #----------------------------#
81             # Reading and Output
82             #----------------------------#
83 3         510 my $in_fh = IO::Zlib->new( $args->[1], "rb" );
84              
85 3         5168 my $out_fh;
86 3 50       16 if ( lc( $opt->{outfile} ) eq "stdout" ) {
87 3         14 $out_fh = *STDOUT;
88             }
89             else {
90 0         0 open $out_fh, ">", $opt->{outfile};
91             }
92              
93 3         25 while ( !$in_fh->eof ) {
94 15         6653 my $line = $in_fh->getline;
95 15 50       2430 next if substr( $line, 0, 1 ) eq "#";
96 15         33 chomp $line;
97              
98 15         59 my $info = App::RL::Common::decode_header($line);
99 15 50       44 next unless App::RL::Common::info_is_valid($info);
100              
101 15 50       56 $info->{chr} =~ s/chr0?//i if $opt->{remove};
102 15         43 my $cur_positions = App::RL::Common::new_set();
103 15         195 $cur_positions->add_pair( $info->{start}, $info->{end} );
104              
105 15 100       985 if ( $opt->{op} eq "overlap" ) {
106 5 50       26 if ( $chrs->has( $info->{chr} ) ) {
107 5         89 my $chr_single = $set_single->{ $info->{chr} };
108 5 100       39 if ( $chr_single->intersect($cur_positions)->is_not_empty ) {
109 2         856 printf {$out_fh} "%s\n", App::RL::Common::encode_header($info);
  2         10  
110             }
111             }
112             }
113              
114 15 100       1338 if ( $opt->{op} eq "non-overlap" ) {
115 5 50       21 if ( $chrs->has( $info->{chr} ) ) {
116 5         87 my $chr_single = $set_single->{ $info->{chr} };
117 5 100       39 if ( $chr_single->intersect($cur_positions)->is_empty ) {
118 3         1207 printf {$out_fh} "%s\n", App::RL::Common::encode_header($info);
  3         14  
119             }
120             }
121             else {
122 0         0 printf {$out_fh} "%s\n", App::RL::Common::encode_header($info);
  0         0  
123             }
124             }
125              
126 15 100       1065 if ( $opt->{op} eq "superset" ) {
127 5 50       19 if ( $chrs->has( $info->{chr} ) ) {
128 5         94 my $chr_single = $set_single->{ $info->{chr} };
129 5 100       36 if ( $chr_single->superset($cur_positions) ) {
130 2         12102 printf {$out_fh} "%s\n", App::RL::Common::encode_header($info);
  2         31  
131             }
132             }
133             }
134             }
135              
136 3         568 $in_fh->close;
137 3         511 close $out_fh;
138             }
139              
140             1;