File Coverage

blib/lib/Proch/Seqfu.pm
Criterion Covered Total %
statement 40 69 57.9
branch 6 40 15.0
condition n/a
subroutine 11 15 73.3
pod 8 8 100.0
total 65 132 49.2


line stmt bran cond sub pod time code
1             package Proch::Seqfu;
2             #ABSTRACT: SeqFu utilities
3              
4 3     3   288844 use strict;
  3         7  
  3         130  
5 3     3   23 use warnings;
  3         7  
  3         221  
6 3     3   64 use 5.014;
  3         17  
7 3     3   17 use Carp qw(confess);
  3         7  
  3         247  
8 3     3   1515 use Data::Dumper;
  3         17779  
  3         285  
9 3     3   2592 use Term::ANSIColor qw(:constants);
  3         34896  
  3         3939  
10 3     3   33 use base 'Exporter';
  3         5  
  3         3639  
11              
12             # Version and configuration
13             our $VERSION = '1.7.0';
14             our $fu_linesize = 0;
15             our $fu_verbose = 0;
16              
17              
18              
19              
20             # Explicitly declare exports
21             our @EXPORT = qw(
22             rc
23             fu_printfasta
24             fu_printfastq
25             verbose
26             has_seqfu
27             seqfu_version
28             is_seq
29             );
30              
31             our @EXPORT_OK = qw($fu_linesize $fu_verbose);
32              
33             # Function to check SeqFu version
34             sub seqfu_version {
35 2     2 1 1759 my $cmd = '';
36            
37 2         7 eval {
38 2         7 my $path = $ENV{PATH};
39 2         17 $path =~ /^(.+)$/; # Untaint PATH by capturing
40 2         24 local $ENV{PATH} = $1;
41 2         16013 $cmd = qx(seqfu version 2>/dev/null);
42 2         150 chomp($cmd);
43             };
44            
45 2 50       40 return -2 if $@;
46 2 50       29 return $cmd if $cmd =~ /^(\d+)\.(\d+)(?:\.(\d+))?$/;
47 2         47 return "-$cmd";
48             }
49              
50             # Function to check if SeqFu is available
51             sub has_seqfu {
52 1     1 1 3161 my $ver = seqfu_version();
53 1 50       50 return 0 if $ver =~ /^-/; # Not installed/error
54 0 0       0 return 1 if length($ver) > 0; # Valid version found
55 0         0 return undef; # Unknown state
56             }
57              
58             # Validate sequence string
59             sub is_seq {
60 3     3 1 696 my $string = $_[0];
61 3 50       14 return 0 unless defined $string;
62 3         24 return $string !~ /[^ACGTRYSWKMBDHVNU]/i;
63             }
64              
65             # Get reverse complement
66             sub rc {
67 1     1 1 282056 my $sequence = reverse($_[0]);
68 1 50       5 return unless is_seq($sequence);
69            
70 1 50       7 if ($sequence =~ /U/i) {
71 0         0 $sequence =~ tr/ACGURYSWKMBDHVacguryswkmbdhv/UGCAYRSWMKVHDBugcayrswmkvhdb/;
72             } else {
73 1         3 $sequence =~ tr/ACGTRYSWKMBDHVacgtryswkmbdhv/TGCAYRSWMKVHDBtgcayrswmkvhdb/;
74             }
75 1         5 return $sequence;
76             }
77              
78             # Print verbose messages
79             sub verbose {
80 0 0   0 1   say STDERR " - ", $_[0] if $fu_verbose;
81             }
82              
83             # Print FASTA format
84             sub fu_printfasta {
85 0     0 1   my ($name, $comment, $seq) = @_;
86 0 0         confess "Error: Name parameter required" unless defined $name;
87 0 0         confess "Error: Sequence parameter required" unless defined $seq;
88 0 0         confess "Error: Invalid sequence characters detected" unless is_seq($seq);
89            
90 0 0         my $print_comment = defined $comment ? ' ' . $comment : '';
91 0           say '>', $name, $print_comment;
92 0           print split_string($seq);
93             }
94              
95             # Print FASTQ format
96             sub fu_printfastq {
97 0     0 1   my ($name, $comment, $seq, $qual) = @_;
98 0 0         confess "Error: Name parameter required" unless defined $name;
99 0 0         confess "Error: Sequence parameter required" unless defined $seq;
100 0 0         confess "Error: Quality string required" unless defined $qual;
101 0 0         confess "Error: Invalid sequence characters detected" unless is_seq($seq);
102 0 0         confess "Error: Sequence and quality length mismatch"
103             unless length($seq) == length($qual);
104            
105 0 0         my $print_comment = defined $comment ? ' ' . $comment : '';
106 0           say '@', $name, $print_comment;
107 0           print split_string($seq), "+\n", split_string($qual);
108             }
109              
110             # Split string into lines
111             sub split_string {
112 0     0 1   my $input_string = $_[0];
113 0 0         return unless defined $input_string;
114            
115 0           my $formatted = '';
116 0           my $line_width = $fu_linesize;
117            
118 0 0         return $input_string . "\n" unless $line_width;
119            
120 0           for (my $i = 0; $i < length($input_string); $i += $line_width) {
121 0           my $frag = substr($input_string, $i, $line_width);
122 0           $formatted .= $frag . "\n";
123             }
124 0           return $formatted;
125             }
126              
127             1;
128              
129             __END__