File Coverage

blib/lib/AlignDB/DeltaG.pm
Criterion Covered Total %
statement 54 54 100.0
branch 5 6 83.3
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 68 69 98.5


line stmt bran cond sub pod time code
1             package AlignDB::DeltaG;
2 2     2   26169 use Moose;
  2         572944  
  2         12  
3 2     2   10358 use YAML::Syck;
  2         2961  
  2         1064  
4              
5             our $VERSION = '1.1.0';
6              
7             has 'temperature' => ( is => 'rw', isa => 'Num', default => sub {37.0}, );
8             has 'salt_conc' => ( is => 'rw', isa => 'Num', default => sub {1.0}, );
9             has 'deltaH' => ( is => 'ro', isa => 'HashRef', );
10             has 'deltaS' => ( is => 'ro', isa => 'HashRef', );
11             has 'deltaG' => ( is => 'ro', isa => 'HashRef', );
12              
13             sub BUILD {
14 3     3 1 4106 my $self = shift;
15              
16             # Load thermodynamic data
17 3         7 my ( $deltaH, $deltaS ) = $self->_load_thermodynamic_data;
18 3         4 $self->{deltaH} = $deltaH;
19 3         4 $self->{deltaS} = $deltaS;
20              
21             # Recalculate the deltaG hash on current temperature and salt conditions
22 3         5 my $deltaG = $self->_init_deltaG;
23 3         4 $self->{deltaG} = $deltaG;
24              
25 3         6 return;
26             }
27              
28             sub polymer_deltaG {
29 3     3 1 22 my $self = shift;
30 3         4 my $polymer = shift;
31              
32 3         17 $polymer = uc $polymer;
33 3 50       8 return if $polymer =~ /[^AGCT]/;
34              
35 3         71 my $deltaG = $self->deltaG;
36              
37 3         4 my $polymer_len = length $polymer;
38 3         3 my $dG = 0;
39              
40             # calculate deltaG
41 3         6 foreach ( 0 .. $polymer_len - 2 ) {
42 73         47 my $nn = substr( $polymer, $_, 2 );
43 73         56 $dG += $deltaG->{$nn};
44             }
45              
46             # terminal correction
47 3         5 my $init_terminal = "init" . substr( $polymer, 0, 1 );
48 3         6 $dG += $deltaG->{$init_terminal};
49              
50 3         4 my $end_terminal = "init" . substr( $polymer, -1, 1 );
51 3         4 $dG += $deltaG->{$end_terminal};
52              
53             # Symmetry correction
54 3         5 my $rc_polymer = $self->_rev_com($polymer);
55 3 100       7 if ( $polymer eq $rc_polymer ) {
56 1         2 $dG += $deltaG->{sym};
57             }
58              
59 3         4 return $dG;
60             }
61              
62             # Load thermodynamic data comes from references
63             sub _load_thermodynamic_data {
64 3     3   2 my $self = shift;
65              
66             #-------------------#
67             # deltaH (kcal/mol)
68             #-------------------#
69 3         35 my %deltaH = qw{
70             AA -7.6 TT -7.6
71             AT -7.2
72             TA -7.2
73             CA -8.5 TG -8.5
74             GT -8.4 AC -8.4
75             CT -7.8 AG -7.8
76             GA -8.2 TC -8.2
77             CG -10.6
78             GC -9.8
79             GG -8.0 CC -8.0
80             initC 0.2 initG 0.2
81             initA 2.2 initT 2.2
82             sym 0.0
83             };
84              
85             #--------------------#
86             # deltaS (cal/K.mol)
87             #--------------------#
88 3         17 my %deltaS = qw{
89             AA -21.3 TT -21.3
90             AT -20.4
91             TA -21.3
92             CA -22.7 TG -22.7
93             GT -22.4 AC -22.4
94             CT -21.0 AG -21.0
95             GA -22.2 TC -22.2
96             CG -27.2
97             GC -24.4
98             GG -19.9 CC -19.9
99             initC -5.7 initG -5.7
100             initA 6.9 initT 6.9
101             sym -1.4
102             };
103              
104 3         6 return ( \%deltaH, \%deltaS );
105             }
106              
107             # Recalculate deltaG by the new temperature and salt_conc values
108             sub _init_deltaG {
109 3     3   3 my $self = shift;
110              
111             # dG = dH - TdS, and dS is dependent on the salt concentration
112 3         79 my $temperature = $self->temperature;
113 3         64 my $salt_conc = $self->salt_conc;
114 3         65 my $deltaH = $self->deltaH;
115 3         60 my $deltaS = $self->deltaS;
116              
117 3         8 my %deltaG = qw{
118             initC 1.96
119             initG 1.96
120             initA 0.05
121             initT 0.05
122             sym 0.43
123             };
124              
125             # the length of each NN dimer is 2, therefore the modifier is 1
126             # total sodium concentration should be above 0.05 M and below 1.1 M
127 3         18 my $entropy_adjust = ( 0.368 * log($salt_conc) );
128              
129 3         3 foreach my $key ( keys %{$deltaH} ) {
  3         13  
130              
131             # the length of each monomer is 1, thus the modifier of dS is 0
132             # and the values are precalulated
133 63 100       89 next if $key =~ /init|sym/;
134              
135 48         50 my $dS = $deltaS->{$key} + $entropy_adjust;
136             my $dG
137 48         52 = $deltaH->{$key} - ( ( 273.15 + $temperature ) * ( $dS / 1000 ) );
138 48         47 $deltaG{$key} = $dG;
139             }
140              
141 3         7 return \%deltaG;
142             }
143              
144             sub _rev_com {
145 3     3   4 my $self = shift;
146 3         2 my $sequence = shift;
147              
148 3         5 $sequence = reverse $sequence; # reverse
149 3         4 $sequence =~ tr/ACGTMRWSYKVHDBN/TGCAKYSWRMBDHVN/; # complement
150              
151 3         4 return $sequence;
152             }
153              
154             1; # Magic true value required at end of module
155              
156             __END__
157              
158             =pod
159              
160             =encoding UTF-8
161              
162             =head1 NAME
163              
164             AlignDB::DeltaG - Calculate deltaG of polymer DNA sequences
165              
166             =head1 SYNOPSIS
167              
168             =over 2
169              
170             =item Normal use
171              
172             use AlignDB::DeltaG
173             my $deltaG = AlignDB::DeltaG->new(
174             temperature => 37,
175             salt_conc => 1,
176             );
177             my $seq = "TAACAAGCAATGAGATAGAGAAAGAAATATATCCA";
178             print "$seq deltaG: ", $deltaG->polymer_deltaG($seq), "\n";
179              
180             =item Reset conditionss
181              
182             use AlignDB::DeltaG;
183             # default value:
184             # temperature => 37,
185             # salt_conc => 1,
186             my $deltaG = AlignDB::DeltaG->new;
187             $deltaG->temperature(30);
188             $deltaG->salt_conc(0.1);
189             $deltaG->BUILD;
190             my $seq = "TAACAAGCAATGAGATAGAGAAAGAAATATATCCA";
191             print "$seq deltaG: ", $deltaG->polymer_deltaG($seq), "\n";
192              
193             =back
194              
195             =head1 DESCRIPTION
196              
197             C<AlignDB::DeltaG> is a simple class to calculate deltaG of polymer DNA sequences using the NN model.
198              
199             In the near future, it may be extanded to calculate oligonucleotide thermodynamics.
200              
201             =head2 Reference
202              
203             1. SantaLucia J, Jr. 2004. Annu Rev Biophys Biomol Struct;
204             2. SantaLucia J, Jr. 1998. Proc Natl Acad Sci U S A;
205              
206             =head1 ATTRIBUTES
207              
208             C<temperature> - default: 37.0 degree centigrade
209              
210             C<salt_conc> - salt concentration, Default: 1 [Na+], in M. Should be above 0.05 M and below 1.1 M
211              
212             C<deltaH> - enthalpy, isa HashRef
213              
214             C<deltaS> - entropy (cal/K.mol), isa HashRef
215              
216             C<deltaG> - free energy, isa HashRef
217              
218             =head1 METHODS
219              
220             =head2 BUILD
221              
222             rebuild the object by the new temperature and/or salt_conc values
223              
224             =head2 polymer_deltaG
225              
226             my $dG = $obj->polymer_deltaG($seq);
227              
228             Calculate deltaG of a given sequence.
229              
230             This method is the main calculating sub.
231              
232             =head1 AUTHOR
233              
234             Qiang Wang <wang-q@outlook.com>
235              
236             =head1 COPYRIGHT AND LICENSE
237              
238             This software is copyright (c) 2008 by Qiang Wang.
239              
240             This is free software; you can redistribute it and/or modify it under
241             the same terms as the Perl 5 programming language system itself.
242              
243             =cut