File Coverage

blib/lib/Chemistry/ESPT/Aprmtop.pm
Criterion Covered Total %
statement 17 102 16.6
branch 0 34 0.0
condition 1 24 4.1
subroutine 4 7 57.1
pod 2 3 66.6
total 24 170 14.1


line stmt bran cond sub pod time code
1             package Chemistry::ESPT::Aprmtop;
2              
3 1     1   36803 use base qw(Chemistry::ESPT::ESSfile);
  1         3  
  1         771  
4 1     1   6 use strict;
  1         2  
  1         26  
5 1     1   4 use warnings;
  1         2  
  1         3096  
6              
7             =head1 NAME
8              
9             Chemistry::ESPT::Aprmtop - AMBER prmtop file object.
10              
11             =head1 SYNOPSIS
12              
13             use Chemistry::ESPT::Aprmtop;
14              
15             my $prmtop = Chemistry::ESPT::Aprmtop->new();
16              
17             =head1 DESCRIPTION
18              
19             This module provides methods to quickly access data contained in an AMBER prmtop file.
20             AMBER prmtop files can only be read currently.
21              
22             =cut
23              
24             our $VERSION = '0.03';
25              
26             =begin comment
27              
28             ### Version History ###
29             0.01 digest prmtop files from Amber9
30             0.02 use integer atomic masses for atom
31             type determination
32             0.03 moved to Chemistry::ESPT namespace
33              
34             ### To Do ###
35             -Explore using Chemistry::Isotope for mass2sym conversion
36              
37             =end comment
38              
39             =head1 ATTRIBUTES
40              
41             All attributes are currently read-only and get populated by reading the assigned ESS file. Attribute values are
42             accessible through the B<$Aprmtop-Eget()> method.
43              
44             =over 15
45              
46             =item CHARGE
47              
48             Total molecular charge given by (total number of protons) - (total Molecular Mechanics charge).
49             Values rounded to nearest integer.
50              
51             =item MMCHARGE
52              
53             Molecular mechanic atomic charges as determined by AMBER stored as an NATOM array.
54              
55             =back
56              
57             =head1 METHODS
58              
59             Method parameters denoted in [] are optional.
60              
61             =over 15
62              
63             =item B<$prmtop-Enew()>
64              
65             Creates a new Aprmtop object
66              
67             =cut
68              
69             ## the object constructor **
70              
71             sub new {
72 1     1 1 12 my $invocant = shift;
73 1   33     9 my $class = ref($invocant) || $invocant;
74 1         10 my $prmtop = Chemistry::ESPT::ESSfile->new();
75              
76 1         5 $prmtop->{PROGRAM} = "AMBER";
77 1         3 $prmtop->{TYPE} = "prmtop";
78              
79             # molecular info
80 1         2 $prmtop->{MMCHARGE} = [];
81              
82 1         3 bless($prmtop, $class);
83 1         3 return $prmtop;
84             }
85              
86              
87             ## methods ##
88              
89             =item B<$prmtop-Eanalyze(filename [spin])>
90            
91             Analyze the spin results in file called filename. Spin defaults to Alpha.
92              
93             =cut
94              
95             # set filename & spin then digest the file
96             sub analyze : method {
97 0     0 1   my $prmtop = shift;
98 0           $prmtop->prepare(@_);
99 0           $prmtop->_digest();
100 0           return;
101             }
102              
103              
104             ## subroutines ##
105              
106             sub _digest {
107              
108 0     0     my $prmtop = shift;
109              
110             # flags & counters
111 0           my $atomflag = 0;
112 0           my @atomicsymbol;
113 0           my $cartflag = 0;
114 0           my $carttot = 0;
115 0           my $chargeflag = 0;
116 0           my $counter = 0;
117 0           my $massflag = 0;
118 0           my $Titleflag = 0;
119              
120             # open filename for reading or display error
121 0 0         open(PRMTOPFILE,$prmtop->{FILENAME}) || die "Could not read $prmtop->{FILENAME}\n$!\n";
122              
123             # grab everything which may be useful
124 0           while (){
125             # skip blank lines
126 0 0         next if /^$/;
127              
128             # title (assume only one line long)
129 0 0         if ( /^\%FLAG\s+TITLE/ ) {
130 0           $Titleflag = 1;
131 0           next;
132             }
133 0 0 0       if ( $Titleflag == 1 && /^[\w\d\-\(\)]+/ ) {
134 0           chomp($_);
135 0           s/\s+$//;
136 0           $prmtop->{TITLE} = $_;
137 0           $Titleflag = 0;
138 0           next;
139             }
140             # Atoms;
141             # Hopefully stored as atomic symbol + an optional id #
142             # seperated by a space(s). Ignore everything
143             # that does not follow this syntax.
144 0 0         if ( /^%FLAG\s+ATOM_NAME/ ) {
145 0           $atomflag = 1;
146 0           $counter = 0;
147 0           next;
148             }
149 0 0 0       if ( $atomflag == 1 && /^((?:[a-zA-Z]{1,2}\d*\s+){1,20})/ ) {
150 0           my @atomsym = split /\s+/, $1, 20;
151 0           for (my $i=0; $i
152             # drop the trailing numbers and spaces
153 0           $atomsym[$i] =~ s/\d+//;
154 0           $atomsym[$i] =~ s/\s+//;
155 0           $atomicsymbol[$counter] = $atomsym[$i];
156 0           $counter++;
157             }
158 0           next;
159             }
160 0 0 0       if ( $atomflag == 1 && /^%FLAG/ ) {
161 0           $atomflag = 0;
162             }
163             # Atomic charges - must be totaled to know molecular charge
164 0 0         if ( /^%FLAG\s+CHARGE/ ) {
165 0           $chargeflag = 1;
166 0           $counter = 0;
167 0           next;
168             }
169 0 0 0       if ( $chargeflag == 1 && /^\s+((?:-*\d\.\d+E[-+]\d{1,2}\s+){1,5})/ ) {
170 0           my @charges = split /\s+/, $1;
171 0           for (my $i=0; $i
172 0           $prmtop->{MMCHARGE} [$counter] = $charges[$i];
173 0           $counter++;
174            
175             }
176 0           next;
177             }
178 0 0 0       if ( $chargeflag == 1 && /^%FLAG/ ) {
179 0           $chargeflag = 0;
180             }
181             # Pick up Atoms from mass section
182             # use integer atomic masses to determine atom
183 0 0         if ( /^%FLAG\s+MASS/ ) {
184 0           $massflag = 1;
185 0           $counter = 0;
186 0           next;
187             }
188 0 0 0       if ( $massflag == 1 && /^\s+((?:-*\d\.\d+E[-+]\d{1,2}\s+){1,5})/ ) {
189 0           my @mass = split /\s+/, $1;
190 0           for (my $i=0; $i
191 0           $prmtop->{ATOMS} [$counter] = mass2sym(sprintf("%.0f", $mass[$i]));
192 0           $counter++;
193             # set NATOMS
194 0           $prmtop->{NATOMS} = $counter;
195             }
196 0           next;
197             }
198 0 0 0       if ( $massflag == 1 && /^%FLAG/ ) {
199 0           $massflag = 0;
200             }
201             }
202              
203             # ensure that all atoms have been properly
204             # assigned an atomic symbol.
205 0           for (my $i=0; $i<$prmtop->{NATOMS}; $i++) {
206 0           $_ = $prmtop->{ATOMS} [$i];
207 0 0         if ( /ArCa|CoNi|BiPo|CmBk/ ) {
208 0 0         if ( exists($atomicsymbol[$i]) ) {
209 0           $prmtop->{ATOMS} [$i] = $atomicsymbol[$i];
210             }
211             }
212             }
213              
214             # determine molecular charge
215 0           my $chargetot = 0;
216 0           my $protontot = 0;
217 0           for (my $i=0; $i<$prmtop->{NATOMS}; $i++) {
218 0           $chargetot = $chargetot + $prmtop->{MMCHARGE} [$i];
219 0           $protontot = $protontot + $prmtop->atomconvert($prmtop->{ATOMS} [$i]);
220             }
221              
222             # convert to integer units of electrons
223 0           $prmtop->{CHARGE} = sprintf("%.0f", $chargetot/18.2223);
224              
225             # correct for negative zeros
226 0 0         $prmtop->{CHARGE} = 0 if $prmtop->{CHARGE} eq "-0";
227              
228             # set multiplicity, 2S+1, assuming highest spin state
229 0           my $electrons = $protontot - $prmtop->{CHARGE};
230 0           $prmtop->{MULTIPLICITY} = $electrons - 2*(int($electrons/2)) + 1;
231              
232             }
233              
234             # utility subroutines
235             sub mass2sym {
236 0     0 0   my (%imass, $result);
237              
238 0           %imass = (
239             1 => "ArCa",
240             4 => "He",
241             7 => "Li",
242             9 => "Be",
243             11 => "B",
244             12 => "C",
245             14 => "N",
246             16 => "O",
247             19 => "F",
248             20 => "Ne",
249             23 => "Na",
250             24 => "Mg",
251             27 => "Al",
252             28 => "Si",
253             31 => "P",
254             32 => "S",
255             35 => "Cl",
256             40 => "ArCa",
257             39 => "K",
258             45 => "Sc",
259             48 => "Ti",
260             51 => "V",
261             52 => "Cr",
262             55 => "Mn",
263             56 => "Fe",
264             59 => "CoNi",
265             64 => "Cu",
266             65 => "Zn",
267             70 => "Ga",
268             73 => "As",
269             79 => "Se",
270             80 => "Br",
271             84 => "Kr",
272             85 => "Rb",
273             88 => "Sr",
274             89 => "Y",
275             91 => "Zr",
276             93 => "Nb",
277             96 => "Mo",
278             98 => "Tc",
279             101 => "Ru",
280             103 => "Rh",
281             106 => "Pd",
282             108 => "Ag",
283             112 => "Cd",
284             115 => "In",
285             119 => "Sn",
286             122 => "Sb",
287             128 => "Te",
288             127 => "I",
289             131 => "Xe",
290             133 => "Cs",
291             137 => "Ba",
292             139 => "La",
293             140 => "Ce",
294             141 => "Pr",
295             144 => "Nd",
296             145 => "Pm",
297             150 => "Sm",
298             152 => "Eu",
299             157 => "Gd",
300             159 => "Tb",
301             162 => "Dy",
302             165 => "Ho",
303             167 => "Er",
304             169 => "Tm",
305             173 => "Yb",
306             175 => "Lu",
307             178 => "Hf",
308             181 => "Ta",
309             184 => "W",
310             186 => "Re",
311             190 => "Os",
312             192 => "Ir",
313             195 => "Pt",
314             197 => "Au",
315             201 => "Hg",
316             204 => "Ti",
317             207 => "Pb",
318             209 => "BiPo",
319             210 => "At",
320             222 => "Rn",
321             223 => "Fr",
322             226 => "Ra",
323             227 => "Ac",
324             232 => "Th",
325             231 => "Pa",
326             238 => "U",
327             237 => "Np",
328             244 => "Np",
329             243 => "Am",
330             247 => "CmBk",
331             251 => "Cf",
332             252 => "Es",
333             257 => "Fm",
334             258 => "Md",
335             259 => "No",
336             260 => "Lr",
337             261 => "Rf",
338             262 => "Ha",
339             );
340              
341 0           my $value = shift;
342 0           $result = $imass{$value};
343 0 0         if ( defined($result) ) {
344 0           return $result;
345              
346             } else {
347 0           return "X";
348             }
349             }
350              
351             1;
352             __END__