File Coverage

blib/lib/My/GenoPheno/Utils.pm
Criterion Covered Total %
statement 20 54 37.0
branch 1 16 6.2
condition 0 5 0.0
subroutine 6 13 46.1
pod 0 9 0.0
total 27 97 27.8


line stmt bran cond sub pod time code
1             package My::GenoPheno::Utils;
2            
3 1     1   83007 use strict;
  1         2  
  1         27  
4 1     1   4 use warnings;
  1         1  
  1         60  
5 1     1   4 use Exporter 'import';
  1         1  
  1         26  
6 1     1   836 use JSON;
  1         10483  
  1         5  
7            
8             our $VERSION = '0.01';
9            
10             # Functions that can be imported
11             our @EXPORT_OK = qw(
12             clean
13             normalise_gene_key
14             normalise_locus_key
15             normalise_raw_gt
16             extract_locus_number
17             parse_locus_header
18             read_json
19             write_json
20             get_excel_value
21             );
22            
23             # --------------------------------------------------
24             # Clean string (trim whitespace)
25             # --------------------------------------------------
26             sub clean {
27 2     2 0 120883 my ($v) = @_;
28 2 50       5 return '' unless defined $v;
29 2         13 $v =~ s/^\s+|\s+$//g;
30 2         9 return $v;
31             }
32            
33             # --------------------------------------------------
34             # Normalise gene key
35             # --------------------------------------------------
36             sub normalise_gene_key {
37 0     0 0 0 my ($gene) = @_;
38 0         0 $gene = clean($gene);
39 0         0 $gene =~ s/[^A-Za-z0-9]//g;
40            
41 0 0       0 if ($gene =~ /^betaCasein$/i) {
42 0         0 return "betaCasein";
43             }
44 0         0 return $gene;
45             }
46            
47             # --------------------------------------------------
48             # Normalise locus key (BC-Locus-X -> betaCasein-Locus-X)
49             # --------------------------------------------------
50             sub normalise_locus_key {
51 0     0 0 0 my ($locus_col) = @_;
52 0         0 $locus_col = clean($locus_col);
53            
54 0 0       0 if ($locus_col =~ /BC-Locus-(\d+)/i) {
55 0         0 return "betaCasein-Locus-$1";
56             }
57            
58 0         0 die "Invalid BC-Locus column name: '$locus_col'\n";
59             }
60            
61             # --------------------------------------------------
62             # Normalise genotype (uppercase, no spaces)
63             # --------------------------------------------------
64             sub normalise_raw_gt {
65 1     1 0 3 my ($gt) = @_;
66 1         3 $gt = clean($gt);
67 1         4 $gt =~ s/\s+//g;
68 1         5 return uc($gt);
69             }
70            
71             # --------------------------------------------------
72             # Extract numeric part from locus key
73             # --------------------------------------------------
74             sub extract_locus_number {
75 0     0 0   my ($text) = @_;
76            
77 0 0 0       die "Invalid locus column name: '$text'\n"
78             unless defined $text && $text =~ /Locus-(\d+)/i;
79            
80 0           return $1;
81             }
82            
83             # --------------------------------------------------
84             # Parse locus header (example: "1: 6_85451043")
85             # --------------------------------------------------
86             sub parse_locus_header {
87 0     0 0   my ($text) = @_;
88 0           $text = clean($text);
89            
90 0 0         if ($text =~ /^(.+?)\s*:\s*(\S+)$/) {
91 0           my $locus_label = clean($1);
92 0           my $chr_position = clean($2);
93 0           return ($locus_label, $chr_position);
94             }
95            
96 0           return (undef, undef);
97             }
98            
99             # --------------------------------------------------
100             # Read JSON file
101             # --------------------------------------------------
102             sub read_json {
103 0     0 0   my ($file) = @_;
104            
105 0 0         open(my $in, "<", $file)
106             or die "Cannot read JSON file $file: $!\n";
107            
108 0           local $/;
109 0           my $json_text = <$in>;
110 0           close $in;
111            
112 0           return JSON->new->utf8(0)->decode($json_text);
113             }
114            
115             # --------------------------------------------------
116             # Write JSON file
117             # --------------------------------------------------
118             sub write_json {
119 0     0 0   my ($file, $data_ref) = @_;
120            
121 0 0         open(my $out, ">", $file)
122             or die "Cannot write JSON file $file: $!\n";
123            
124 0           print $out JSON->new->utf8(0)
125             ->canonical(1)
126             ->pretty(1)
127             ->encode($data_ref);
128            
129 0           close $out;
130             }
131            
132             # --------------------------------------------------
133             # Read value from Excel sheet structure
134             # --------------------------------------------------
135             sub get_excel_value {
136 0     0 0   my ($sheet, $col_ref, $row, $col_name) = @_;
137            
138 0 0         return '' unless exists $col_ref->{$col_name};
139            
140 0   0       return $sheet->{cell}[ $col_ref->{$col_name} ][$row] // '';
141             }
142            
143             # --------------------------------------------------
144             1; # VERY IMPORTANT (module must return true)