File Coverage

blib/lib/FASTX/ScriptHelper.pm
Criterion Covered Total %
statement 149 199 74.8
branch 31 82 37.8
condition 11 32 34.3
subroutine 26 28 92.8
pod 11 11 100.0
total 228 352 64.7


line stmt bran cond sub pod time code
1             package FASTX::ScriptHelper;
2             #ABSTRACT: Shared routines for binaries using FASTX::Reader and FASTX::PE.
3              
4 2     2   138669 use 5.012;
  2         23  
5 2     2   10 use warnings;
  2         3  
  2         74  
6 2     2   3127 use File::Fetch;
  2         176873  
  2         76  
7 2     2   15 use Carp qw(confess cluck);
  2         5  
  2         134  
8 2     2   1352 use Data::Dumper;
  2         13916  
  2         124  
9 2     2   1042 use FASTX::Reader;
  2         7  
  2         92  
10 2     2   14 use File::Basename;
  2         3  
  2         130  
11 2     2   15 use File::Spec;
  2         4  
  2         52  
12 2     2   1378 use Term::ANSIColor qw(color);
  2         19434  
  2         1454  
13 2     2   1549 use JSON::PP;
  2         28205  
  2         137  
14 2     2   1146 use Capture::Tiny qw(capture);
  2         8709  
  2         119  
15 2     2   13 use Time::HiRes qw( time );
  2         3  
  2         8  
16 2     2   166 use Scalar::Util qw( blessed refaddr reftype);
  2         3  
  2         4588  
17             $FASTX::ScriptHelper::VERSION = '0.1.2';
18              
19             our @ISA = qw(Exporter);
20             our @EXPORT = qw(rc fu_printfasta fu_printfastq verbose);
21             our @EXPORT_OK = qw($fu_linesize $fu_verbose); # symbols to export on request
22              
23              
24             sub new {
25              
26             # Instantiate object
27 3     3 1 1031 my ($class, $args) = @_;
28              
29 3         15 my %accepted_parameters = (
30             'verbose' => 1,
31             'debug' => 1,
32             'logfile' => 1,
33             'linesize'=> 1,
34             );
35              
36 3         15 my $valid_attributes = join(', ', keys %accepted_parameters);
37              
38 3         7 for my $parameter (keys %{ $args} ) {
  3         11  
39             confess("Attribute <$parameter> is not expected. Valid attributes are: $valid_attributes\n")
40 7 100       283 if (! $accepted_parameters{$parameter} );
41             }
42              
43              
44             my $self = {
45             logfile => $args->{logfile} // undef,
46             debug => $args->{debug} // 0,
47             verbose => $args->{verbose} // 0,
48 2   50     36 linesize => $args->{linesize} // 0,
      50        
      50        
      50        
49             };
50 2         7 my $object = bless $self, $class;
51              
52             # Regular log file
53 2 50       18 if (defined $self->{logfile}) {
54 2         12 verbose($self, "Ready to log in $object->{logfile}");
55 2   33     247 open my $logfh, '>', "$object->{logfile}" || confess("ERROR: Unable to write log file to $object->{logfile}\n");
56 2         10 $object->{logfh} = $logfh;
57 2         8 $object->{do_log} = 1;
58             } else {
59             # Set {logfh} to Stderr, but do not set {do_log}
60 0         0 $object->{logfh} = *STDERR;
61             }
62              
63 2         10 return $object;
64             }
65              
66              
67              
68             sub fu_printfasta {
69              
70 2     2 1 427 my $self = undef;
71 2 50       10 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
72 2         8 $self = shift @_;
73             }
74              
75 2         12 my ($name, $comment, $seq) = @_;
76 2 50       6 confess("No sequence provided for $name") unless defined $seq;
77 2         8 my $print_comment = '';
78 2 50       14 if (defined $comment) {
79 0         0 $print_comment = ' ' . $comment;
80             }
81              
82 2         20 say '>', $name, $print_comment;
83 2 50       14 if ($self) {
84 2         11 print split_string($self,$seq);
85             } else {
86 0         0 print split_string($seq);
87             }
88              
89             }
90              
91              
92             sub fu_printfastq {
93 0     0 1 0 my $self = undef;
94 0 0       0 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
95 0         0 $self = shift @_;
96             }
97 0         0 my ($name, $comment, $seq, $qual) = @_;
98 0         0 my $print_comment = '';
99 0 0       0 if (defined $comment) {
100 0         0 $print_comment = ' ' . $comment;
101             }
102 0 0       0 $qual = 'I' x length($seq) unless (defined $qual);
103 0         0 say '@', $name, $print_comment;
104 0 0       0 if ($self) {
105 0         0 print split_string($self,$seq) , "+\n", split_string($self,$qual);
106             } else {
107 0         0 print split_string($seq) , "+\n", split_string($qual);
108             }
109              
110             }
111              
112              
113             sub rc {
114 1     1 1 892 my $self = undef;
115 1 50       6 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
116 1         3 $self = shift @_;
117             }
118 1         3 my $sequence = reverse($_[0]);
119 1 50       3 if (is_seq($sequence)) {
120 1         4 $sequence =~tr/ACGTacgt/TGCAtgca/;
121 1         6 return $sequence;
122             }
123             }
124              
125              
126             sub is_seq {
127 1     1 1 2 my $self = undef;
128 1 50       4 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
129 0         0 $self = shift @_;
130             }
131 1         2 my $string = shift @_;
132 1 50       5 if ($string =~/[^ACGTRYSWKMBDHVN]/i) {
133 0         0 return 0;
134             } else {
135 1         30 return 1;
136             }
137             }
138              
139              
140             sub split_string {
141 2     2 1 4 my $self = undef;
142 2 50       5 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
143 2         4 $self = shift @_;
144             }
145 2         8 my $input_string = shift @_;
146 2 50       12 confess("No string provided") unless $input_string;
147 2         8 my $formatted = '';
148 2   33     11 my $line_width = $self->{linesize} // $main::opt_line_size // 0; # change here
      0        
149              
150 2 50       6 return $input_string. "\n" unless ($line_width);
151 2         7 for (my $i = 0; $i < length($input_string); $i += $line_width) {
152 2         9 my $frag = substr($input_string, $i, $line_width);
153 2         10 $formatted .= $frag."\n";
154             }
155 2         8 return $formatted;
156             }
157              
158              
159             sub verbose {
160 2     2 1 5 my $self = undef;
161 2 50       7 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
162 2         7 $self = shift @_;
163             }
164 2         7 my ($message, $reference, $reference_name, @remainder) = @_;
165 2 50 33     16 if ($remainder[0]) {
    50          
166 0         0 $message .= $reference . $reference_name . join('', @remainder);
167 0         0 $reference = undef;
168 0         0 $reference_name = undef;
169             } elsif (defined $reference and reftype $reference eq undef) {
170             # Mistakenly passed list instead of string
171 0         0 $message .= $reference;
172 0 0       0 if (defined $reference_name) {
173 0         0 $message .= $reference_name;
174 0         0 $reference_name = undef;
175             }
176 0         0 $reference = undef;
177              
178             }
179 2   50     11 my $variable_name = $reference_name // 'data';
180 2         8 my $timestamp = _getTimeStamp();
181 2 50 33     19 if ( (defined $self and $self->{verbose} ) or (defined $main::opt_verbose and $main::opt_verbose) ) {
      0        
      33        
182             # Print
183 2 50       8 if (defined $self->{do_log}) {
184 0         0 $self->writelog($message, $reference, $reference_name);
185             }
186 2         11 say STDERR color('cyan'),"[$timestamp]", color('reset'), " $message";
187 2 50       172 say STDERR color('magenta'), Data::Dumper->Dump([$reference], [$variable_name])
188             if (defined $reference);
189             } else {
190             # No --verbose, don't print
191 0         0 return -1;
192             }
193              
194             }
195              
196              
197              
198             sub writelog {
199 3     3 1 805 my $self = undef;
200 3 50       22 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
201 3         14 $self = shift @_;
202             }
203              
204 3         17 my ($message, $reference, $reference_name) = @_;
205 3   50     44 my $variable_name = $reference_name // 'data';
206 3         15 my $timestamp = _getTimeStamp();
207 3         92 say {$self->{logfh}} "[$timestamp] $message";
  3         54  
208 3 50       27 say {$self->{logfh}} Data::Dumper->Dump([$reference], [$variable_name]) if (defined $reference);
  0         0  
209              
210              
211             }
212              
213              
214              
215              
216             sub download {
217 0     0 1 0 my $begin_time = time();
218 0         0 my $self = undef;
219 0 0       0 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
220 0         0 $self = shift @_;
221             }
222              
223 0         0 my ($url, $destination) = @_;
224 0 0       0 if (defined $self->{do_log}) {
225 0         0 $self->writelog( qq(Downloading "$url") );
226             }
227              
228              
229 0         0 my $downloader = File::Fetch->new(uri => $url);
230 0 0       0 my $file_path = $downloader->fetch( to => $destination ) or confess($downloader->error);
231 0         0 my $end_time = time();
232 0         0 say Dumper $downloader;
233 0         0 my $duration = sprintf("%.2fs", $end_time - $begin_time);
234 0         0 return $file_path;
235             }
236              
237             sub run {
238 1     1 1 5 my $begin_time = time();
239 1         2 my $time_stamp = _getTimeStamp();
240 1         3 my $self = undef;
241 1 50       7 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
242 1         4 $self = shift @_;
243             }
244 1         7 my %valid_attributes = (
245             candie => 1,
246             logall => 1,
247             );
248              
249              
250 1         3 my ($command, $options) = @_;
251 1         4 _validate_attributes(\%valid_attributes, $options, 'run');
252 1 50       3 if (defined $self) {
253 1         5 $self->writelog("Shell> $command");
254             }
255              
256              
257 1         5 my $cmd = _runCmd($command);
258 1 50       16 if ($cmd->{exit}) {
259 0         0 $cmd->{failed} = 1;
260 0 0       0 if (! $options->{candie}) {
261 0         0 confess("Execution of an external command failed:\n$command");
262             }
263             }
264 1         12 my $end_time = time();
265 1         10 $cmd->{time} = $time_stamp;
266 1         23 $cmd->{duration} = sprintf("%.2fs", $end_time - $begin_time);
267 1 50       13 if (defined $self) {
268 1 50       4 if ($options->{logall}) {
269 0         0 $self->writelog(" +> Output: $cmd->{stdout}");
270 0         0 $self->writelog(" +> Messages: $cmd->{stderr}");
271             }
272 1         17 $self->writelog(" +> Elapsed time: $cmd->{duration}; Exit status: $cmd->{exit};");
273              
274             }
275              
276 1         13 return ($cmd);
277              
278              
279             }
280              
281              
282             sub cpu_count {
283 1 50   1 1 614 if ( $^O =~ m/linux/i ) {
    0          
284 1         5218 my($num) = qx(grep -c ^processor /proc/cpuinfo);
285 1 50       84 return $1 if $num =~ m/^(\d+)/;
286             }
287             elsif ( $^O =~ m/darwin/i ) {
288 0         0 my($num) = qx(system_profiler SPHardwareDataType | grep Cores);
289 0 0       0 return $1 if $num =~ /.*Cores: (\d+)/;
290             }
291 0         0 return 1;
292             }
293              
294             sub _getTimeStamp {
295              
296 6     6   252 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
297 6         56 my $timestamp = sprintf ( "%04d-%02d-%02d %02d:%02d:%02d",
298             $year+1900,$mon+1,$mday,$hour,$min,$sec);
299 6         21 return $timestamp;
300             }
301              
302              
303             sub _validate_attributes {
304 1     1   2 my ($hash_ref, $options, $title) = @_;
305              
306 1         2 for my $attr (sort keys %{ $options } ) {
  1         6  
307 1 50       1 confess "Invalid attribute '$attr' used calling routine '$title'\n" if (not defined ${ $hash_ref}{ $attr });
  1         5  
308             }
309 1         2 return;
310             }
311             sub _runCmd {
312 1 50   1   13 if ( ref($_[0]) eq 'FASTX::ScriptHelper' ) {
313 0         0 shift @_;
314             }
315 1         5 my @cmd = @_;
316 1         51 my $output;
317 1         10 $output->{cmd} = join(' ', @cmd);
318              
319             my ($stdout, $stderr, $exit) = capture {
320 1     1   5391 system( @cmd );
321 1         35 };
322 1         1330 chomp($stderr);
323 1         7 chomp($stdout);
324 1         8 $output->{stdout} = $stdout;
325 1         10 $output->{stderr} = $stderr;
326 1         10 $output->{exit} = $exit;
327              
328 1         16 return $output;
329             }
330              
331              
332              
333             1;
334              
335             __END__