File Coverage

blib/lib/App/Rangeops/Common.pm
Criterion Covered Total %
statement 115 142 80.9
branch 13 22 59.0
condition n/a
subroutine 16 17 94.1
pod 0 4 0.0
total 144 185 77.8


line stmt bran cond sub pod time code
1             package App::Rangeops::Common;
2 10     10   1045 use strict;
  10         13  
  10         290  
3 10     10   39 use warnings;
  10         13  
  10         238  
4 10     10   550 use autodie;
  10         13427  
  10         46  
5              
6 10     10   35386 use 5.010001;
  10         54  
7              
8 10     10   40 use Carp;
  10         15  
  10         766  
9 10     10   8129 use Graph;
  10         940613  
  10         441  
10 10     10   8131 use IPC::Cmd;
  10         564259  
  10         566  
11 10     10   6844 use List::MoreUtils;
  10         88551  
  10         74  
12 10     10   13665 use Path::Tiny;
  10         98525  
  10         807  
13 10     10   6014 use YAML::Syck;
  10         17144  
  10         702  
14              
15 10     10   6247 use AlignDB::IntSpan;
  10         105628  
  10         361  
16 10     10   5575 use App::RL::Common;
  10         745987  
  10         396  
17 10     10   5747 use App::Fasops::Common;
  10         92280  
  10         14120  
18              
19             sub build_info {
20 159     159 0 154 my $line_refs = shift;
21 159         158 my $info_of = shift;
22              
23 159 100       280 if ( !defined $info_of ) {
24 10         16 $info_of = {};
25             }
26              
27 159         142 for my $line ( @{$line_refs} ) {
  159         216  
28 265         1082 for my $part ( split /\t/, $line ) {
29 653         1020 my $info = App::RL::Common::decode_header($part);
30 653 100       49753 next unless App::RL::Common::info_is_valid($info);
31              
32 534 100       11034 if ( !exists $info_of->{$part} ) {
33 262         567 $info_of->{$part} = $info;
34             }
35             }
36             }
37              
38 159         2241 return $info_of;
39             }
40              
41             sub build_info_intspan {
42 4     4 0 8 my $line_refs = shift;
43 4         5 my $info_of = shift;
44              
45 4 100       15 if ( !defined $info_of ) {
46 3         5 $info_of = {};
47             }
48              
49 4         7 for my $line ( @{$line_refs} ) {
  4         12  
50 36         81 for my $part ( split /\t/, $line ) {
51 72         133 my $info = App::RL::Common::decode_header($part);
52 72 50       5952 next unless App::RL::Common::info_is_valid($info);
53              
54 72         1481 $info->{intspan} = AlignDB::IntSpan->new;
55 72         1102 $info->{intspan}->add_pair( $info->{start}, $info->{end} );
56              
57 72 100       2921 if ( !exists $info_of->{$part} ) {
58 57         137 $info_of->{$part} = $info;
59             }
60             }
61             }
62              
63 4         13 return $info_of;
64             }
65              
66             sub sort_links {
67 10     10 0 15 my $line_refs = shift;
68 10         26 my $numeric = shift;
69              
70 10         14 my @lines = @{$line_refs};
  10         40  
71              
72             #----------------------------#
73             # Cache info
74             #----------------------------#
75 10         35 my $info_of = build_info( \@lines );
76              
77             #----------------------------#
78             # Sort within links
79             #----------------------------#
80 10         24 for my $line (@lines) {
81 116         225 my @parts = split /\t/, $line;
82 116         155 my @invalids = grep { !exists $info_of->{$_} } @parts;
  265         403  
83 116         111 my @ranges = grep { exists $info_of->{$_} } @parts;
  265         356  
84              
85             # chromosome strand
86 236         324 @ranges = map { $_->[0] }
87 124         706 sort { $a->[1] cmp $b->[1] }
88 116         112 map { [ $_, $info_of->{$_}{strand} ] } @ranges;
  236         1059  
89              
90             # start point on chromosomes
91 236         374 @ranges = map { $_->[0] }
92 122         657 sort { $a->[1] <=> $b->[1] }
93 116         170 map { [ $_, $info_of->{$_}{start} ] } @ranges;
  236         928  
94              
95             # chromosome name
96 116 50       207 if ($numeric) {
97 0         0 @ranges = map { $_->[0] }
98 0         0 sort { $a->[1] <=> $b->[1] }
99 0         0 map { [ $_, $info_of->{$_}{chr} ] } @ranges;
  0         0  
100             }
101             else {
102 236         329 @ranges = map { $_->[0] }
103 122         634 sort { $a->[1] cmp $b->[1] }
104 116         109 map { [ $_, $info_of->{$_}{chr} ] } @ranges;
  236         940  
105             }
106              
107 116         374 $line = join "\t", ( @ranges, @invalids );
108             }
109              
110             #----------------------------#
111             # Sort by first range's chromosome order among links
112             #----------------------------#
113             {
114             # after swapping, remove dups again
115 10         46 @lines = sort @lines;
116 10         45 @lines = List::MoreUtils::PP::uniq(@lines);
117              
118             # strand
119 102         145 @lines = map { $_->[0] }
120 200         248 sort { $a->[1] cmp $b->[1] }
121             map {
122 10         353 my $first = ( split /\t/ )[0];
  102         502  
123 102         238 [ $_, $info_of->{$first}{strand} ]
124             } @lines;
125              
126             # start
127 102         117 @lines = map { $_->[0] }
128 204         231 sort { $a->[1] <=> $b->[1] }
129             map {
130 10         41 my $first = ( split /\t/ )[0];
  102         456  
131 102         234 [ $_, $info_of->{$first}{start} ]
132             } @lines;
133              
134             # chromosome name
135 10 50       47 if ($numeric) {
136 0         0 @lines = map { $_->[0] }
137 0         0 sort { $a->[1] <=> $b->[1] }
138             map {
139 0         0 my $first = ( split /\t/ )[0];
  0         0  
140 0         0 [ $_, $info_of->{$first}{chr} ]
141             } @lines;
142             }
143             else {
144 102         118 @lines = map { $_->[0] }
145 200         229 sort { $a->[1] cmp $b->[1] }
146             map {
147 10         20 my $first = ( split /\t/ )[0];
  102         446  
148 102         251 [ $_, $info_of->{$first}{chr} ]
149             } @lines;
150             }
151             }
152              
153             #----------------------------#
154             # Sort by copy number among links (desc)
155             #----------------------------#
156             {
157 10         21 @lines = map { $_->[0] }
  10         30  
  102         119  
158 202         167 sort { $b->[1] <=> $a->[1] }
159             map {
160 10         15 [ $_, scalar( grep { exists $info_of->{$_} } split( /\t/, $_ ) ) ]
  102         145  
  223         312  
161             } @lines;
162             }
163              
164 10         306 return \@lines;
165             }
166              
167             sub get_seq_faidx {
168 0     0 0   my $filename = shift;
169 0           my $location = shift; # I:1-100
170              
171             # get executable
172 0           my $bin;
173 0           for my $e (qw{samtools}) {
174 0 0         if ( IPC::Cmd::can_run($e) ) {
175 0           $bin = $e;
176 0           last;
177             }
178             }
179 0 0         if ( !defined $bin ) {
180 0           confess "Could not find the executable for [samtools]\n";
181             }
182              
183 0           my $cmd = sprintf "%s faidx %s %s", $bin, $filename, $location;
184 0           open my $pipe_fh, '-|', $cmd;
185              
186 0           my $seq;
187 0           while ( my $line = <$pipe_fh> ) {
188 0           chomp $line;
189 0 0         if ( $line =~ /^[\w-]+/ ) {
190 0           $seq .= $line;
191             }
192             }
193 0           close $pipe_fh;
194              
195 0           return $seq;
196             }
197              
198             1;